gen_server
回调的 Module:terminate
文档说:
即使gen_server进程不是监督树的一部分,这个 如果函数收到“退出”函数,则会调用该函数。来自其父母的消息。 原因与“退出”中的原因相同。消息。
以下是我的handle_info
和terminate
功能:
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]
Here是decode_msg
内gen_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
回调函数,这是预期的行为。在解释退出信号时似乎存在差异,无论进程是否与其父进程相关联。
答案 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/1
或erlang:exit/2
工作已经预料到了。
- 如果Pid没有捕获退出,Pid本身会以退出原因退出。
- 如果Pid正在捕获退出,退出信号将转换为消息{&#39; EXIT&#39;,From,Reason}并传送到Pid的消息队列。
因此,目前您的代码陷阱'EXIT'
发出信号,因为此代码会像任何其他消息一样发送到邮箱并匹配handle_info/2
通配符模式。
如果您想了解更多相关信息,可以阅读gen_server
源代码并了解其工作原理。您还可以找到此代码中描述的your problem。