[erlang-bugs] handling of uncaught exceptions in behavour callbacks

Fred Hebert <>
Wed Apr 25 17:33:25 CEST 2012


I would also agree to see this as a bug.

Regarding the fix, wouldn't rewriting it to use a try ... of ... catch 
negate the problem entirely by being able to make the distinction 
between a throw and a returned value?

try Mod:some_callback(...) of
     ...
     Other -> exit({bad_return_value, Other}
catch
     _:Reason -> exit(Reason)
end

or something similar, as long as we keep similar error/exit semantics? I 
figure the throw could be seen as the standard bubbling thing where 
throw becomes an error, which becomes an error before the process dies.

On 12-04-25 4:43 AM, Richard Carlsson wrote:
> When gen_server, gen_fsm, etc., make a call to one of the behaviour 
> callback functions, these calls are protected by a construct on the 
> following form (simplified):
>
>     case catch Mod:some_callback(...) of
>         ...
>         {'EXIT',Reason} -> exit(Reason);
>         Other -> exit({bad_return_value, Other})
>     end
>
> When a callback terminates with an exception of type 'error' or 
> 'exit', this sort of does the expected thing (although it converts 
> error exceptions to exit exceptions, which might or might not be 
> intended). But if the callback terminates due to an uncaught 
> throw(Term), it is treated as if the callback had returned Term. At 
> best, this is an undocumented and horrible way of letting you write 
> callback functions that can do things like throw({reply, Reply, 
> NewState}) for nonlocal return out of a deep recursion and back to the 
> gen_server code. But I'd like to think that it's simply unintended 
> behaviour. (Nothing I could see in the OTP documentation describes 
> what the gen_server is supposed to do with exceptions thrown from a 
> callback.)
>
> The annoyance this causes is that if you use throw(X) for anything 
> within the callback (or in library code called by the callback) and 
> you don't make sure to wrap your callback in something that catches 
> all throws, any such uncaught exception will result in the gen_server 
> process terminating with the confusing reason {bad_return_value, X} 
> (and no stack trace to indicate where X was thrown from).
>
> If it can be agreed that this is a bug that should be fixed (and how), 
> we could submit a patch.
>
>     /Richard Carlsson and Samuel Rivas
> _______________________________________________
> erlang-bugs mailing list
> 
> http://erlang.org/mailman/listinfo/erlang-bugs


More information about the erlang-bugs mailing list