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