哥们,
我对Erlang gen_server有疑问
代码插曲在这里:
文件:akita_cluster_info.erl
start_link() -> gen_server:start_link({global, ?MODULE}, ?MODULE, [], []). init([]) -> c:nl(akita_collector_local), rpc:multicall(akita_collector_local, start, []), {ok, #state{}}.
file:akita_collector_local.erl
start() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). init([]) -> %%process_flag(trap_exit, true), init_dets_file(), io:format("dic: ~w~n", [get()]), {ok, #state{}}.
shell的输出如下:
不要陷阱退出:
Eshell V5.9.1(以^ G中止)
(秋田@浩)1> akita_cluster_info:START_LINK()
。 dic:[{'$ ancestors',[< 0.50.0>]},{'$ initial_call',{akita_collector_local,init,1}}]
收到信息:{init_dets,{akita @ hao,ok}}
{确定,< 0.48.0>}
(秋田@浩)2 - ;
陷阱退出:
Eshell V5.9.1(以^ G中止)
(秋田@浩)1> akita_cluster_info:START_LINK()
。 dic:[{'$ ancestors',[< 0.50.0>]},{'$ initial_call',{akita_collector_local,init,1}}] 原因终止:正常
收到信息:{init_dets,{akita @ hao,ok}}
收到信息:{collector_close,{akita @ hao,normal}}
{确定,< 0.48.0>}
(秋田@浩)2 - ;
当process_flag(trap_exit, true)
未注释时, akita_collector_local gen_server进程将立即退出,因为其父进程(在rpc:multicall中生成)将终止。我知道这是正常的。
有什么奇怪的是,当没有process_flag(trap_exit, true)
时, akita_collector_local gen_server进程可以存活 !!由于它不能捕获出口,它应该立即退出。 (这个理论是正确的,我在Erlang shell中测试过)。但是为什么在这种情况下gen_server进程不会退出。我不知道。
你能帮助我吗?非常感谢。
BRS,
阮
ps:我觉得棘手的部分可能在于 rpc:multicall
答案 0 :(得分:3)
我认为这是因为rpc:multicall中生成的流程退出的原因是 正常 。
如果链接了两个进程,如果其中一个进程以 正常 的原因退出,则另一个没有trap_exit的进程将不存在。
当process_flag(trap_exit, true)
没有评论时,在gen_server.erl的源代码中,我们可以看到:
346 decode_msg(Msg, Parent, Name, State, Mod, Time, Debug, Hib) ->
347 case Msg of
348 {system, From, Req} ->
349 sys:handle_system_msg(Req, From, Parent, ?MODULE, Debug,
350 [Name, State, Mod, Time], Hib);
351 {'EXIT', Parent, Reason} ->
352 terminate(Reason, Name, Msg, Mod, State, Debug);
只要其父(生成gen_server的进程)退出,Gen_server将自动终止。