Question

I have the following code in Erlang, in which I'm mecking an nonexistent module. In some versions of Erlang/meck this generates an exception that seems uncatchable.

Anyone knows if there is an "uncatchable exception" feature in Erlang ?

try
    meck:new(i_dont_exist),
    io:format("No exception in this version of Erlang ... :( "),
    no_problems
catch
    exit:_ -> exit;
    error:_ -> error;
    throw:_ -> throw;
    _:_ -> what_class_is_it
    after
        io.format("in the after~n")
end.

When I execute this code this is what I get (notice that not even the "after" clause is being executed so it looks more like a bug to me):

** exception exit: {undefined_module,i_dont_exist}
     in function  meck_proc:resolve_can_expect/3 (src/meck_proc.erl, line 402)
     in call from meck_proc:init/1 (src/meck_proc.erl, line 194)
     in call from gen_server:init_it/6 (gen_server.erl, line 304)
     in call from proc_lib:init_p_do_apply/3 (proc_lib.erl, line 227)

I have also tried with the "catch" expression with the same result:

> catch meck:new(i_dont_exist).
** exception exit: {undefined_module,i_dont_exist}
     in function  meck_proc:resolve_can_expect/3 (src/meck_proc.erl, line 402)
     in call from meck_proc:init/1 (src/meck_proc.erl, line 194)
     in call from gen_server:init_it/6 (gen_server.erl, line 304)
     in call from proc_lib:init_p_do_apply/3 (proc_lib.erl, line 227)
Was it helpful?

Solution

What's happening here is that meck:new spawns a new process (a gen_server process using the meck_proc callback module), and that process exits with the undefined_module error. (You can get it not to do that by passing the non_strict option to meck:new.) This new process is linked to the calling process, which means that an exit signal will be sent to the calling process, and the calling process will exit as well, without being able to catch the signal.

You can avoid that by making your calling process trap exits:

process_flag(trap_exit, true)

which will turn the exit signal into a message that you can receive; see the manual for more details. However, as a general rule you should avoid trapping exits, as it makes error handling more complicated (as opposed to the default "crash, restart").

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top