gen_server can't trap 'EXIT' from parent
Fredrik Thulin
ft@REDACTED
Mon Jan 10 21:46:14 CET 2005
I have a gen_server that I start 'manually' (not using a supservisor)
with gen_server:start_link/3.
In the init/1 function I do process_flag(trap_exit, true).
I do this to try and make my application as robust as possible. The
gen_server was a SIP server transaction handler, and my idea was that
it should notify the originator of the SIP request with a SIP error in
case anything happened in my application. It therefor needed to be
linked with the application process, to be able to detect if it
crashed.
I scratched my head for a good two hours tonight trying to figure out
why I didn't receive the exit signals in my handle_info/2 function, but
instead could just notice that my terminate/2 function got called when
the parent process terminated. Regardless of how much I had set
trap_exit to true - regardless of where I did it. I could even see that
it was still set inside terminate/2 by calling process_info(self(),
trap_exit).
I goggled for another hour or so, but found no explanation there. It
seemed as if the general understanding were that you could do trap_exit
in gen_servers to get {'EXIT', ...} signals from processes to whom you
had links, instead of getting terminated.
I then looked at the source. In R10B-2, gen_server.erl, inside loop(...)
(the MAIN loop), this code is found :
Msg = receive
...
case Msg of
...
{'EXIT', Parent, Reason} ->
terminate(Reason, Name, Msg, Mod, State, Debug);
...
Right! That explains it. If the 'EXIT' comes from your gen_servers
parent (almost always your supervisor I guess) then you can't trap it!
Just thought I would send a message to the list, mainly for the archives
since no matter how stupid I think it is for a gen_server to have EXITs
from it's parent handled differently, I don't imagine it would ever be
changed.
I did find a way around it, although it isn't very elegant. A comment
near the top of gen.erl (where the common start-functions for the
general behaviors are) says
%% If spawn without link, set parent to our selves "self"!!!
So if you do gen_server:start(... self() ...) instead of start_link(...)
and then, in the init/1 function, you link to the parents pid and do
your process_flag(trap_exit, true) it seems to work. You then get
'EXIT' signals when the gen_servers parent terminates, and I haven't
observed any bad effects from it this far.
Time for rest.
/Fredrik
More information about the erlang-questions
mailing list