【发布时间】:2017-04-09 11:21:59
【问题描述】:
简单代码:
-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.
在外壳中:
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 以退出原因 Reason 终止,则发送“DOWN”消息 到 Pid1:
{'DOWN', Ref, process, Pid2, Reason}如果 Pid2 不存在,则立即发送“DOWN”消息 原因设置为 noproc。
【问题讨论】:
-
如果在
Pid1 ! hello.之前添加timer:sleep(100),会得到预期的输出吗? -
@Dogbert,是的!这似乎表明
spawn()异步执行。
标签: erlang