Erlang OTP 内部细节之gen_server
如果gen_server进程需要在死亡的时候调用terminate函数,则需要调用process_flag(trap_exit, true)设置为系统进程。但是什么时候需要在handle_info中处理{'EXIT', FROM, REASON}消息呢?我的观点是,如果我们在继承了gen_server的进程中关联了其他进程(不包括父进程,如supervisor进程),那么就需要在handle_info中捕获这条消息,如果只是和父进程关联(如supervisor进程)则不需要捕获该消息,因为在gen_server模块内自动捕获了来自父进程的{'EXIT', FROM, REASON}消息,gen_server处理消息的代码如下
decode_msg(Msg, Parent, Name, State, Mod, Time, Debug, Hib) ->
case Msg of
{system, From, get_state} ->
sys:handle_system_msg(get_state, From, Parent, ?MODULE, Debug,
{State, [Name, State, Mod, Time]}, Hib);
{system, From, {replace_state, StateFun}} ->
NState = try StateFun(State) catch _:_ -> State end,
sys:handle_system_msg(replace_state, From, Parent, ?MODULE, Debug,
{NState, [Name, NState, Mod, Time]}, Hib);
{system, From, Req} ->
sys:handle_system_msg(Req, From, Parent, ?MODULE, Debug,
[Name, State, Mod, Time], Hib);
{'EXIT', Parent, Reason} -> %% 如果退出消息是父进程发送来的,则调用terminate消息
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消息处理如下:
terminate(Reason, Name, Msg, Mod, State, Debug) ->
case catch Mod:terminate(Reason, State) of
{'EXIT', R} ->
error_info(R, Name, Msg, State, Debug),
exit(R);
_ ->
case Reason of
normal ->
exit(normal);
shutdown ->
exit(shutdown);
{shutdown,_}=Shutdown ->
exit(Shutdown);
_ ->
FmtState =
case erlang:function_exported(Mod, format_status, 2) of
true ->
Args = [get(), State],
case catch Mod:format_status(terminate, Args) of
{'EXIT', _} -> State;
Else -> Else
end;
_ ->
State
end,
error_info(Reason, Name, Msg, FmtState, Debug),
exit(Reason)
end
end.
terminate/6函数只是调用了继承gen_server行为的termniate函数
最是那一低头的温柔,恰似水莲花不胜凉风的娇羞,
道一声珍重,道一声珍重,那一声珍重里有无数甜蜜的忧愁

浙公网安备 33010602011771号