Search code examples
erlangerlang-shell

Why does erlang shell receive exit message from spawned processes only once?


Here is code:

Erlang/OTP 20 [erts-9.1] [source] [64-bit] [smp:2:2] [ds:2:2:10] [async-threads:10] [kernel-poll:false]

Eshell V9.1  (abort with ^G)
1> process_flag(trap_exit, true).
false
2> spawn_link(fun() -> exit(reason) end).
<0.63.0>
3> receive X -> X after 0 -> 'end' end.
{'EXIT',<0.63.0>,reason}
4> spawn_link(fun() -> exit(reason) end).
<0.66.0>
5> receive X -> X after 0 -> 'end' end.  
'end'

Why doesn't erlang shell receive exit message from second spawned process?


Solution

  • After the first receive succeeds, X gets bound to its returned value, which is {'EXIT', <...>, reason}. Since you use the same variable X in the second receive, receive waits for a message that exactly matches the old value of X, which won't match the second message because its PID is different than the first one.

    To fix this, you can either use a different variable name:

    1> process_flag(trap_exit, true).
    false
    2> spawn_link(fun() -> exit(reason) end).
    <0.67.0>
    3> receive X -> X after 0 -> 'end' end.
    {'EXIT',<0.67.0>,reason}
    4> X.
    {'EXIT',<0.67.0>,reason}
    5> spawn_link(fun() -> exit(reason) end).
    <0.71.0>
    6> receive X2 -> X2 after 0 -> 'end' end.
    {'EXIT',<0.71.0>,reason}
    

    or you can "forget" the value of X using f/1 and then use X again (this will only work in the REPL):

    7> spawn_link(fun() -> exit(reason) end).
    <0.74.0>
    8> f(X).
    ok
    9> receive X -> X after 0 -> 'end' end.
    {'EXIT',<0.74.0>,reason}