我正在生成2个进程,看来我无法杀死其中两个进程:
restarter
-每当worker
发生故障时产生的过程worker
-从shell获取消息,将它们连接起来并在退出的reason
中将它们返回到重启器的过程,该重启器又将它们转发到shell。 worker
进程无法终止,因为restarter
会在任何陷阱退出消息上重新启动它。但是什么使restarter
进程保持活力?
-module(mon).
-compile_flags([debug_info]).
-export([worker/1,init/0,restarter/2,clean/1]).
% ctrl+g
init()->
Pid=spawn(?MODULE,restarter,[self(),[]]),
register(restarter,Pid),
Pid.
restarter(Shell,Queue)->
process_flag(trap_exit,true),
Wk=spawn_link(?MODULE,worker,[Queue]),
register(worker,Wk),
receive
{'EXIT',Pid,{Queue,normal}}->Shell ! {Queue,"From res: worker died peacefully, wont restart"};
{'EXIT',Pid,{Queue,horrible}} ->
Shell ! {Queue,"Processed so far:"},
Shell ! "will restart in 5 seconds, select fresh/stale -> 1/0",
receive
1 ->
Shell ! "Will restart fresh",
restarter(Shell,[]);
0 ->Shell ! "Will continue work",
restarter(Shell,Queue)
after 5000 ->
Shell ! "No response -> started with 666",
restarter(Shell,[666])
end;
{MSG}->Shell ! {"Unknown message...closing",MSG}
end.
worker(Queue)->
receive
die->exit({Queue,horrible});
finish->exit({Queue,normal});
MSG->worker([{time(),MSG}|Queue])
end.
用法
mon:init().
regs(). %worker and restarter are working
whereis(worker) ! "msg 1", whereis(worker) ! "msg2".
whereis(worker) ! finish.
flush(). % should get the first clause from restarter
regs(). % worker should be up and running again
exit(whereis(restarter),reason).
regs(). % restarter should be dead
答案 0 :(得分:3)
在这种情况下,restarter
进程正在捕获出口,因此exit(whereis(restarter), reason)
不会杀死它。退出信号被转换为消息,并被放入进程的消息队列中:
> process_info(whereis(restarter), messages).
{messages,[{'EXIT',<0.76.0>,reason}]}
它仍在消息队列中的原因是receive
表达式中没有任何子句与此消息匹配。前两个子句特定于worker
进程使用的退出原因,最后一个子句看起来像是一个包罗万象的子句,但实际上并非如此-它匹配具有一个元素的元组的任何消息。如果将其写为MSG
而不是{MSG}
,则它将收到退出原因消息,并向外壳发送“未知消息”。
如果您真的想终止该进程,请使用kill
原因:
exit(whereis(restarter), kill).
kill
退出信号是不可捕获的,即使进程正在捕获退出。
另一件事:只有当工作队列为空时,前两个接收子句才会匹配。那是因为它重用了变量名Queue
,所以{'EXIT',Pid,{Queue,normal}}
中的队列必须等于作为参数传递给restarter
函数的值。在这种情况下,通常会在接收子句中使用NewQueue
或其他变量。