[erlang-bugs] [erlang-questions] Strange behaviour of exit(kill)
Fred Hebert
mononcqc@REDACTED
Fri Oct 9 03:41:39 CEST 2015
On 10/09, Roland Karlsson wrote:
>So Robert, tell me who missed it.
>What is the difference in behaviour when using exit/1 or exit/2?
>And is the difference still there if the process kills itself with exit/2?
>
>/Roland
>
exit/1 raises a 'kill' exception (you can do it with erlang:raise(exit,
kill, Stacktrace)) that will unwind the stack and can be caught by try
... catch. In the case where the exception is not caught, the process is
terminated and the reason of its death forwarded as a signal.
exit/2 sends an exit signal asynchronously.
The confusing aspect is that a 'kill' signal sent by exit/2 is
untrappable, but a 'kill' signal that comes from a process terminating
after an exception doesn't.
This means the underlying secret is you have 2 levels of signals (at
least):
- termination signals (uncaught exception create one of these, dying
from any other signal does the same)
- kill signals (untrappable)
The interesting bit then is why is there a need to translate 'kill' into
'killed'? From what I can tell, it's just so you can know the process
was brutally killed -- if you only had 'kill' then you know it came from
an exception. Buuuut here's the kicker:
1> spawn_link(fun() -> exit(kill) end), flush().
Shell got {'EXIT',<0.87.0>,kill}
ok
2> spawn_link(fun() -> spawn_link(fun() -> exit(kill) end),
timer:sleep(infinity) end), flush().
Shell got {'EXIT',<0.89.0>,killed}
3> spawn_link(fun() -> process_flag(trap_exit, true), spawn_link(fun()
-> exit(kill) end), timer:sleep(infinity) end), flush().
ok
woops. There's no real consistency there. In the end:
- a special 'kill' signal that cannot be trapped will unconditionally
kill a process and produce a signal 'killed' for peer processes
- an exception 'kill' bubbling up is reported as a trappable exit signal
with the reason 'kill'
- that 'kill' exit signal is converted to 'killed' for other processes,
regardless of the source, as long as it's not from a local stack.
This just sounds like a leaky abstraction where the conversion of kill
-> killed only takes place on incoming signals being converted,
unconditionally. Still, you have two types of signals: untrappable
(exit(Pid, kill)), and trappable (anything else, even with a reason
kill, if produced from a stacktrace).
It's confusing and always has been so.
More information about the erlang-bugs
mailing list