簡單代碼:運行報表給出不同的輸出
-module(on_exit).
-export([on_exit/2, test/0]).
on_exit(Pid, Fun) ->
spawn(fun() ->
Ref = erlang:monitor(process, Pid),
receive
{'DOWN', Ref, process, Pid, Why} ->
Fun(Why)
end
end).
test() ->
Fun1 = fun() -> receive Msg -> list_to_atom(Msg) end end,
Pid1 = spawn(Fun1),
Fun2 = fun(Why) -> io:format("~w died with error: ~w~n", [Pid1, Why]) end,
_Pid2 = spawn(on_exit, on_exit, [Pid1, Fun2]),
Pid1 ! hello.
在shell:
1> c(on_exit).
{ok,on_exit}
2> on_exit:test().
<0.39.0> died with error: noproc
hello
3>
=ERROR REPORT==== 9-Apr-2017::05:16:54 ===
Error in process <0.39.0> with exit value: {badarg,[{erlang,list_to_atom,[hello],[]},{on_exit,'-test/0-fun-0-',0,[{file,"on_exit.erl"},{line,14}]}]}
預期輸出:
5> Pid1 ! hello.
<0.35.0> died with error: {badarg,[{erlang,list_to_atom,[hello],[]}]}
hello
6>
=ERROR REPORT==== 9-Apr-2017::05:15:47 ===
Error in process <0.35.0> with exit value: {badarg,[{erlang,list_to_atom,[hello],[]}]}
事實上,預期輸出是我看看我是否將test()中的每行都粘貼到了shell中。爲什麼我在函數內運行相同的行時會出現noproc(無進程)錯誤?
從docs:
12.8監視器
的替代方法鏈路監視器。進程Pid1可以通過調用BIF erlang:monitor(process,Pid2)爲Pid2創建一個 監視器。 函數返回一個引用Ref。
如果PID2與退出原因原因終止,一個「向下」消息被髮送 到PID1:
{'DOWN', Ref, process, Pid2, Reason}
如果PID2不存在時,「向下」消息被立即用 原因集發送到noproc。
如果您在Pid1之前添加'timer:sleep(100)',您會得到預期的輸出! hello.'? – Dogbert
@Dogbert,是的!這似乎表明'spawn()'異步執行。 – 7stud