问题描述
我正在学习erlang与书,在第13章,第一个练习是写一个函数my_spawn,当生成的消息崩溃/退出时捕获退出消息。 - 模(my_spawn1)。
-compile(export_all)。
my_spawn(Mod,Func,Args) - >
{M1,S1,Mi1} = os:timestamp(),
Pid = spawn(Mod,Func,Args),
lib_misc:on_exit(Pid,fun(Why)
{M2,S2,Mi2} = os:timestamp(),
ElapsedTime =(M2 - M1)* 1000000 +(S2 - S1)* 1000 +(Mi2-Mi1),
io:format(〜p death with:〜p〜n消费时间:〜p(ms),[Pid,Why,ElapsedTime]),
end),
Pid。
我的困惑是,如果在spawn_monitor之后, Mod:Func(Args)
已经完成,但$ code> lib_misc:on_exit(...)没有设置,所以退出消息会丢失,真的吗?
如果这是正确的,那么如何捕捉这种情况?
[由Pascal编辑] / strong>
我添加了lib_misc的代码:on_exit / 2
on_exit(Pid,Fun) - >
spawn(fun() - >
process_flag(trap_exit,true),%%< label id =code.onexit1/>
link(Pid),%%< ; label id =code.onexit2/>
接收
{'EXIT',Pid,为什么} - > %%< label id =code.onexit3/>
Fun(为什么)%%< label id =code.onexit4/>
end
end)。
函数on_exit的第一件事是产生一个将process_flag trap_exit设置为true的进程,因此它是受到保护的而不是崩溃,而是会收到以下类型的消息: {'EXIT',Pid,Why}
。
在下一行,它尝试将自身链接到Pid; 2例可能:
- Pid不存在(错误的值,已经死了...),那么on_exit进程将会收到消息
{'EXIT',Pid,noproc}
并调用F(noproc)。 - Pid存在,那么on_exit进程将等待收到,直到过程Pid死于一些原因。 on_exit将收到
{'EXIT',Pid,Reason}
并调用F(Reason)。
我不明白你为什么谈论spawn_monitor,在你的情况下不会使用它。无论如何,如果在on_exit函数中用monitor(process,Pid)代替链接(Pid),甚至不需要使用trap_exit,因为如果Pid死了,监视器功能不会崩溃。在所有情况下,它返回消息 {'DOWN',MonitorReference,process,Pid,Reason}
。 on_exit可以这样修改:
on_exit(Pid,Fun) - >
spawn(fun() - >
MonitorReference = monitor(process,Pid),
receive
{'DOWN',MonitorReference,process,Pid,Why} - >乐趣(为什么)
end
end)。
I am learning erlang with book , In chapter 13, the first exercise is writing a function my_spawn, which catch exit message when spawned message crash/exited.
-module(my_spawn1).
-compile(export_all).
my_spawn(Mod,Func,Args) ->
{M1, S1, Mi1} = os:timestamp(),
Pid = spawn(Mod,Func,Args),
lib_misc:on_exit(Pid, fun(Why) ->
{M2,S2,Mi2} = os:timestamp(),
ElapsedTime = (M2 - M1) * 1000000 + (S2 - S1) * 1000 + (Mi2-Mi1),
io:format("~p died with:~p~n consume time:~p(ms)", [Pid,Why,ElapsedTime]),
end),
Pid.
my confuse was, if after spawn_monitor, the Mod:Func(Args)
was finished, but the lib_misc:on_exit(...)
haven't setup, so the exit message will be lost, really ?
If that's correct, so how to catch this situation ?
[edit by Pascal]
I add the code for lib_misc:on_exit/2
on_exit(Pid, Fun) ->
spawn(fun() ->
process_flag(trap_exit, true), %% <label id="code.onexit1"/>
link(Pid), %% <label id="code.onexit2"/>
receive
{'EXIT', Pid, Why} -> %% <label id="code.onexit3"/>
Fun(Why) %% <label id="code.onexit4"/>
end
end).
The first thing the function on_exit does is to spawn a process that set the process_flag trap_exit to true, thus it is "protected" from crashes, and will receive instead messages of the type: {'EXIT', Pid, Why}
.
On the next line it tries to link itself to Pid; 2 cases are possible:
- the Pid does not exists (wrong value, already dead...) then the on_exit process will receive the message
{'EXIT', Pid, noproc}
and will call F(noproc). - the Pid exists, then the on_exit process will wait on receive until the process Pid dies for some Reason. on_exit will receive
{'EXIT', Pid, Reason}
and call F(Reason).
I don't understand why you speak about spawn_monitor, it is not used in your case. Anyway, if you replace link(Pid) by monitor(process,Pid) in the on_exit function, you even don't need to use trap_exit since the monitor function don't crash if the Pid is dead. In all cases it returns the message {'DOWN',MonitorReference,process,Pid,Reason}
. on_exit could be modified like this:
on_exit(Pid, Fun) ->
spawn(fun() ->
MonitorReference = monitor(process,Pid),
receive
{'DOWN',MonitorReference,process,Pid,Why} -> Fun(Why)
end
end).
这篇关于erlang竞赛条件的产卵和接收的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!