[erlang-bugs] handling of uncaught exceptions in behavour callbacks
Richard Carlsson
carlsson.richard@REDACTED
Wed Apr 25 10:43:55 CEST 2012
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
More information about the erlang-bugs
mailing list