[erlang-questions] Programming question

Samuel Rivas <>
Fri Jan 26 09:01:22 CET 2007


Ulf Wiger (TN/EAB) wrote:
> I agree that gen_server shouldn't touch the EXIT 
> messages. While changing this might cause some 
> consternation among a few users with legacy code, 
> I believe the current behaviour violates the 
> principle of least astonishment and, as you've
> described, can lead to highly unexpected timing bugs.
> 
> gen:call() doesn't enable exit trapping under any 
> circumstances (nor does it link to the server), 
> so if the process is trapping exits, and is linked
> to the server, it is certainly because someone else 
> made it so. It is then reasonable to expect that 
> some other code expects an EXIT message to arrive.

  There is another issue with the catch sentence in the block that
handles call requests in gen_server.erl:


    call(Name, Request) ->
        case catch gen:call(Name, '$gen_call', Request) of
	    {ok,Res} ->
	        Res;
    	    {'EXIT',Reason} ->
	        exit({Reason, {?MODULE, call, [Name, Request]}})
        end.

    call(Name, Request, Timeout) ->
        case catch gen:call(Name, '$gen_call', Request, Timeout) of
	    {ok,Res} ->
	        Res;
	    {'EXIT',Reason} ->
	        exit({Reason, {?MODULE, call, [Name, Request, Timeout]}})
        end.


  That does not do well with the behaviour that a try-catch user
expects. An uncatched signal becomes a return term. So a gen_server with
the next code:


    handle_call(trhow_it, _From, State) ->
        throw(ouch),
        {reply, ok, State};

    handle_call(weird, _From, State) ->
        throw({reply, ok, State}),
        {stop, ok, State};

    handle_call(expected, _From, State) ->
        erlang:error({nocatch, ouch}),
        {reply, ok, State}.


  Behaves as funny as:


    16> gen_server_throw:start_link().  
    {ok,<0.78.0>}
    17> gen_server:call(test, weird).   
    ok
    18> gen_server:call(test, trhow_it).

    =ERROR REPORT==== 26-Jan-2007::08:47:46 ===
    ** Generic server test terminating 
    ** Last message in was trhow_it
    ** When Server state == {}
    ** Reason for termination == 
    ** {bad_return_value,ouch}
    ** exited: {bad_return_value,ouch} **
    19> gen_server_throw:start_link().  
    ok,<0.83.0>}
    20> gen_server:call(test, expected).

    =ERROR REPORT==== 26-Jan-2007::08:48:07 ===
    ** Generic server test terminating 
    ** Last message in was expected
    ** When Server state == {}
    ** Reason for termination == 
    ** {{nocatch,ouch},
        [{gen_server_throw,handle_call,3},
         {gen_server,handle_msg,6},
         {proc_lib,init_p,5}]}
    ** exited: {{nocatch,ouch},
                [{gen_server_throw,handle_call,3},
                 {gen_server,handle_msg,6},
                 {proc_lib,init_p,5}]} **


  - I would expect that 'throw_it' caused an exception similar
    to 'expected' (with the right stack trace)
  - I would expect that 'weird' caused a similar exception too, but it
    does not even crash the server.

  I did not find any mention about throw issues in the manual either.

Regards
-- 
	Samuel



More information about the erlang-questions mailing list