Search code examples
erlangelixir

Erlang/Elixir reraise equivalent for `catch :exit, e ->`?


I'd like to catch and look at an :exit catch and decide programatically if I actually wanted to catch it or not.

Is it possible to reraise these :exit values, like Elixir reraise does with normal errors?

try do
  ... some code ...
rescue
  e ->
    ...
    reraise e, __STACKTRACE__ # this is fine
  :exit, e ->
    ...
    reraise e, __STACKTRACE__ # what do I write here to preserve both :exit and stack trace?
end
  • Process.exit replaces the stack trace
  • Process.raise skips :exit and replaces stack trace
  • reraise e, __STACKTRACE__ skips :exit
** (ArgumentError) raise/1 and reraise/2 expect a module name, string or exception as the first argument, got: {:noproc, {GenServer, :call, [:asdf, :woop, 5000]}}

Any Erlang/Elixir/beam solution is appreciated. Even an Erlang core solution would be helpful.


Solution

  • Simplest solution: just use exit function:

      def foo do
        process_call()
      catch :exit, e ->
        # do some handling here
        exit(e)
      end
    

    If you want to keep stacktrace of a process where you called function foo, you can modify e which has a shape of {{error, stacktrace_inside_process}, process_call_info}. Here is a quick example:

      def foo do
        process_call()
      catch :exit, {{error, stacktrace_inside_process}, process_call_info} ->
        # do some handling here
        exit({{error, stacktrace_inside_process ++ __STACKTRACE__}, process_call_info})
      end