List 如何在列表中重新启动erlang进程?

List 如何在列表中重新启动erlang进程?,list,erlang,List,Erlang,我有这样一个列表结构: [{Value, spawn_link(fun() -> worker(Value, self()) end)} || Value <- List] [{Value,spawn_link(fun()->worker(Value,self())end)}|Value使用erlang:monitor/2监视您的进程: List1 = [{Value, spawn_link(fun() -> worker(Value, self()) end)} || Va

我有这样一个列表结构:

[{Value, spawn_link(fun() -> worker(Value, self()) end)} || Value <- List]

[{Value,spawn_link(fun()->worker(Value,self())end)}|Value使用erlang:monitor/2监视您的进程:

List1 = [{Value, spawn_link(fun() -> worker(Value, self()) end)} || Value <- List],
List2 = [{Value, Pid, monitor(process, Pid)} || {Value, Pid} <- List1]

List1=[{Value,spawn_link(fun()->worker(Value,self())end)}| | Value首先,创建一个函数,该函数创建一个进程,该进程监视
Pid
并在其死亡时执行
fun
,如下所示:

on_exit(Pid, Fun) ->
    spawn(fun() ->
                  Ref = monitor(process, Pid),
                  receive
                      {'DOWN', Ref, process, Pid, Why} ->
                          Fun(Why)
                  end
          end).
现在,您可以使用退出时的
on\u exit
函数来创建一个创建进程的函数,该进程将在进程终止时自动重新启动:

keep_alive(Fun) ->
    process_flag(trap_exit, true),
    Pid = spawn_link(Fun),
    on_exit(Pid, fun(Why) ->
                         io:format("Process died: ~p, restarting it~n", [Why]),
                         keep_alive(Fun) end),
    Pid.
有了这两个小函数,您创建将自动重新启动的进程的工作就简化为在列表中调用
keep_alive

[{Value, keep_alive(fun() -> worker(Value, self()) end)} || Value <- List].

[{Value,keep_alive(fun()->worker(Value,self())end)}|Value在自制的管理器中,不要忘记设置
process_标志(trap_exit,true)
否则它会同时死亡一个孩子,然后所有其他孩子也会死亡:

1> F = fun() -> timer:sleep(2000) end.
#Fun<erl_eval.20.80484245>
2> F1 = fun() -> timer:sleep(2000), 1/0 end.
#Fun<erl_eval.20.80484245>
3> S = fun() -> spawn_link(F), receive M-> M after 5000 -> no_message end end.
#Fun<erl_eval.20.80484245>
4> S1 = fun() -> spawn_link(F1), receive M-> M after 5000 -> no_message end end.
#Fun<erl_eval.20.80484245>
5> S1b = fun() -> process_flag(trap_exit, true), spawn_link(F1), receive M-> M after 5000 -> no_message end end.
#Fun<erl_eval.20.80484245>
6> self().
<0.40.0>
7> S().                                                                                   
no_message            
8> self().
<0.40.0>
9> S1().  

=ERROR REPORT==== 15-Mar-2014::06:46:27 ===
Error in process <0.49.0> with exit value: {badarith,[{erlang,'/',[1,0],[]}]}

** exception exit: badarith
     in operator  '/'/2
        called as 1 / 0
10> self().
<0.50.0>
11> S1b(). 

=ERROR REPORT==== 15-Mar-2014::06:46:39 ===
Error in process <0.53.0> with exit value: {badarith,[{erlang,'/',[1,0],[]}]}

{'EXIT',<0.53.0>,{badarith,[{erlang,'/',[1,0],[]}]}}
12> self().
<0.50.0>
13> 
1>F=fun()->计时器:睡眠(2000)结束。
#乐趣
2> F1=fun()->计时器:睡眠(2000),1/0结束。
#乐趣
3> S=fun()->spawn_link(F),在5000->no_消息结束后接收M->M。
#乐趣
4> S1=fun()->spawn_link(F1),接收M->M after 5000->no_消息结束。
#乐趣
5> S1b=fun()->进程标志(陷阱退出,true),生成链接(F1),5000后接收M->M->无消息结束。
#乐趣
6> self()。
7> S()。
没有消息
8> self()。
9> S1()。
=错误报告===2014年3月15日::06:46:27===
进程中存在错误,退出值为:{badarith,[{erlang,'/',[1,0],]}
**异常退出:badarith
在运算符“/”中/2
称为1/0
10> self()。
11> S1b()。
=错误报告===2014年3月15日::06:46:39===
进程中存在错误,退出值为:{badarith,[{erlang,'/',[1,0],]}
{'EXIT',{badarith,[{erlang,'/',[1,0],]}]}
12> self()。
13> 

除非您这样做是出于教育目的,否则我建议您使用erlang otp supervisors,采用一对一的重启策略。

为什么不使用otp来管理您的工作人员呢?它很好;)它有竞争条件。当您的进程在退出/2时
生成自己的监视进程之前死亡时,它将关闭进程执行ting
keep_alive/1
这样它就不会工作了,除非你设置了
trap_exit
标志,你根本不提。嗨,@Hynek Pichi Vychodil!接得好,伙计,我会更新答案的。