为什么我不能杀死 Erlang 进程?
Why i can't kill Erlang process?
我正在生成 2 个进程,但似乎我无法杀死其中任何一个:
restarter
- 每当 worker
关闭时生成 的进程
worker
- 从 shell 获取消息的进程,将它们连接起来并 returns 它们在 reason
出口的 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
在这种情况下,restarter
进程正在捕获退出,因此 exit(whereis(restarter), reason)
不会终止它。退出信号被转换为消息,并被放入进程的消息队列中:
> process_info(whereis(restarter), messages).
{messages,[{'EXIT',<0.76.0>,reason}]}
它仍在邮件队列中的原因是 receive
表达式中的 none 个子句与此邮件匹配。前两个子句特定于 worker
进程使用的退出原因,最后一个子句可能看起来像一个包罗万象的子句,但实际上并非如此——它匹配任何具有一个元素的元组消息.如果它被写成 MSG
而不是 {MSG}
,它会收到退出原因消息,并发送 "Unknown message" 到 shell.
如果真的要杀进程,使用kill
原因:
exit(whereis(restarter), kill).
A kill
退出信号是不可捕获的,即使进程正在捕获退出也是如此。
另一件事:前两个接收子句只有在工作队列为空时才会匹配。那是因为它重用了变量名 Queue
,所以 {'EXIT',Pid,{Queue,normal}}
中的队列必须等于作为参数传递给 restarter
函数的值。在这种情况下,您通常会使用 NewQueue
或其他内容作为接收子句中的变量。
我正在生成 2 个进程,但似乎我无法杀死其中任何一个:
restarter
- 每当worker
关闭时生成 的进程
worker
- 从 shell 获取消息的进程,将它们连接起来并 returns 它们在reason
出口的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
在这种情况下,restarter
进程正在捕获退出,因此 exit(whereis(restarter), reason)
不会终止它。退出信号被转换为消息,并被放入进程的消息队列中:
> process_info(whereis(restarter), messages).
{messages,[{'EXIT',<0.76.0>,reason}]}
它仍在邮件队列中的原因是 receive
表达式中的 none 个子句与此邮件匹配。前两个子句特定于 worker
进程使用的退出原因,最后一个子句可能看起来像一个包罗万象的子句,但实际上并非如此——它匹配任何具有一个元素的元组消息.如果它被写成 MSG
而不是 {MSG}
,它会收到退出原因消息,并发送 "Unknown message" 到 shell.
如果真的要杀进程,使用kill
原因:
exit(whereis(restarter), kill).
A kill
退出信号是不可捕获的,即使进程正在捕获退出也是如此。
另一件事:前两个接收子句只有在工作队列为空时才会匹配。那是因为它重用了变量名 Queue
,所以 {'EXIT',Pid,{Queue,normal}}
中的队列必须等于作为参数传递给 restarter
函数的值。在这种情况下,您通常会使用 NewQueue
或其他内容作为接收子句中的变量。