garrison
Why can't I catch Process.exit/2?
Alright, fair warning: I may be missing something obvious here.
I can use try/catch to catch an exit sent with exit/1:
try
exit(:timeout)
catch
:exit, :timeout -> :ok
end
But if I catch an exit sent with Process.exit/2, it doesn’t work (it exits):
try
Process.exit(self(), :timeout)
:timer.sleep(1000)
catch
:exit, :timeout -> :ok
end
What’s really getting me here is I can’t find any mention of this in the docs. I managed to find one random comment which mentions this fact completely off-hand, and that’s it.
Am I missing something?
Marked As Solved
cevado
elixir function Kernel.exit/1 delegates to erlang exit/1 while Process.exit/2 delegates to erlang exit/2.
if you read the erlang documentation:
exit/1 raises an exception:
Raises an exception of class
exitwith exit reasonReason.
erlang — erts v15.2.1
while exit/2 sends an exit signal:
Sends an exit signal with exit reason
Reasonto the process or port identified byPid.
erlang — erts v15.2.1
that’s why a catch can handle an exit/1 call but not an exit/2.
You can get more details on erlang doc for processes:
https://www.erlang.org/doc/system/ref_man_processes.html
Also Liked
jswanner
I suppose this is the documentation you were looking for:
The functions
erlang:exit/1anderlang:exit/2are named similarly but provide very different functionalities. Theerlang:exit/1function should be used when the intent is to stop the current process whileerlang:exit/2should be used when the intent is to send an exit signal to another process. Note also thaterlang:exit/1raises an exception that can be caught whileerlang:exit/2does not cause any exception to be raised.
derek-zhou
You are correct. Ask yourself this question: Why try … catch should catch asynchronous event? Do you expect this to catch also?
Process.exit(self(), :timeout)
try
:timer.sleep(1000)
catch
:exit, :timeout -> :ok
end
You can; you just need to do Process.flag(:trap_exit, true) and have a handle_info clause to handle the {:EXIT, pid, reason} message that you would receive.
jswanner
I think you want to look at Process.flag/2 and the meaning of :trap_exit. It still won’t do what you want, as you’ll need to handle it by receiving the message in the process mailbox
derek-zhou
Exactly. My point is, to do what you want it to do, the sleep would need to be enhanced to install a clean up callback and raise when something else happened. It is a lot of work for no apparent gain. The Elixir document on sleep is clear that you should not use it: Process — Elixir v1.18.2
Use this function with extreme care. For almost all situations where you would use sleep/1 in Elixir, there is likely a more correct, faster and precise way of achieving the same with message passing







