无监督的gen_server在收到退出信号时不会调用终止

时间:2016-09-10 21:06:52

标签: erlang otp gen-server

关于gen_server回调的

Module:terminate文档说:

  

即使gen_server进程不是监督树的一部分,这个   如果函数收到“退出”函数,则会调用该函数。来自其父母的消息。   原因与“退出”中的原因相同。消息。

以下是我的handle_infoterminate功能:

handle_info(UnknownMessage, State) ->
    io:format("Got unknown message: ~p~n", [UnknownMessage]),
    {noreply, State}.

terminate(Reason, State) ->
    io:format("Terminating with reason: ~p~n", [Reason]).

我使用gen_server:start启动此服务器。我假设当我呼叫erlang:exit(Pid, fuckoff)时,它应该调用terminate回调函数。但它显示:

Got unknown message: {'EXIT',<0.33.0>,fuckoff}

这意味着它正在调用handle_info。但是当我打电话给gen_server:stop时,一切都按照文档中的说明进行。我是从shell调用gen_server的。你能澄清一下吗?

[UPDATE]

Heredecode_msggen_server函数的源代码。如果它收到任何&#39; EXIT&#39;消息它应该调用terminate函数:

decode_msg(Msg, Parent, Name, State, Mod, Time, Debug, Hib) ->
    case Msg of
    {system, From, Req} ->
        sys:handle_system_msg(Req, From, Parent, ?MODULE, Debug,
                  [Name, State, Mod, Time], Hib);
    {'EXIT', Parent, Reason} ->
        terminate(Reason, Name, Msg, Mod, State, Debug);
    _Msg when Debug =:= [] ->
        handle_msg(Msg, Parent, Name, State, Mod);
    _Msg ->
        Debug1 = sys:handle_debug(Debug, fun print_event/3,
                      Name, {in, Msg}),
        handle_msg(Msg, Parent, Name, State, Mod, Debug1)
end.

在我的情况下,它不会调用terminate函数。

[UPDATE]

当我使用gen_server启动gen_server:start_link()时,使用erlang:exit(Pid, Reason)发送退出信号将导致调用terminate回调函数,这是预期的行为。在解释退出信号时似乎存在差异,无论进程是否与其父进程相关联。

2 个答案:

答案 0 :(得分:2)

简答:

如果从exit/2 actor内部调用gen_server函数,它将根据文档按预期运行,并且将调用terminate/2回调。

答案很长:

当您从shell发送退出消息时,退出元组的Parent值设置为shell进程ID,另一方面当您启动gen_server进程表单shell时Parent 1}} value设置为自己的进程id,而不是shell进程id,因此当它获得退出消息时,它不匹配decode_msg/8函数中接收块的第二个子句,因此{{ 1}}函数未被调用,最后匹配的下一个子句正在调用terminate/6函数。

<强>建议:

为了通过向handle_msg/5进程发送退出消息来调用terminate/3回调,您可以在gen_server中捕获退出消息,然后按停止元组返回,如下所示:< / p>

handle_info/2

答案 1 :(得分:0)

当您启动gen_server时,这是一个简单的过程,因此,erlang:exit/1erlang:exit/2工作已经预料到了。

  
      
  • 如果Pid没有捕获退出,Pid本身会以退出原因退出。
  •   
  • 如果Pid正在捕获退出,退出信号将转换为消息{&#39; EXIT&#39;,From,Reason}并传送到Pid的消息队列。
  •   

因此,目前您的代码陷阱'EXIT'发出信号,因为此代码会像任何其他消息一样发送到邮箱并匹配handle_info/2通配符模式。

如果您想了解更多相关信息,可以阅读gen_server源代码并了解其工作原理。您还可以找到此代码中描述的your problem