Question

buddies,
i have a question about Erlang gen_server.
Code episode is here:
file: 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{}}.  

The output from the shell is like:
do not trap exit:

Eshell V5.9.1 (abort with ^G)
(akita@hao)1> akita_cluster_info:start_link().
dic: [{'$ancestors',[<0.50.0>]},{'$initial_call',{akita_collector_local,init,1}}]
receive info: {init_dets,{akita@hao,ok}}
{ok,<0.48.0>}
(akita@hao)2>

trap exit:

Eshell V5.9.1 (abort with ^G)
(akita@hao)1> akita_cluster_info:start_link().
dic: [{'$ancestors',[<0.50.0>]},{'$initial_call',{akita_collector_local,init,1}}] terminated with Reason: normal
receive info: {init_dets,{akita@hao,ok}}
receive info: {collector_close,{akita@hao,normal}}
{ok,<0.48.0>}
(akita@hao)2>

When process_flag(trap_exit, true) is not commented, the akita_collector_local gen_server process will exit immediately because its parent process (that generated in rpc:multicall) dies. I know this is normal.
What is weird is that when there is no process_flag(trap_exit, true), the akita_collector_local gen_server process can survive!! Since it can not trap exit, it should have exitted right away. (this theory is right and i tested in Erlang shell). But why the gen_server process does not exit in this case. I have no idea.
Can you help me? Thank you very much.
Brs,
Ruan

ps: i figure the tricky part maybe lie in rpc:multicall

Was it helpful?

Solution

I think it is because the process generated in rpc:multicall exited with the reason normal.

When two processes are linked, if one of them exits with the reason normal, the other one without trap_exit won't exist.

And when process_flag(trap_exit, true) is not commented, in the source code of gen_server.erl, we can see this:

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 will terminate automatically as long as its parent (The process which generates the gen_server) exits.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top