Erlang simple_one_for_one 主管不重启孩子

Posted

技术标签:

【中文标题】Erlang simple_one_for_one 主管不重启孩子【英文标题】:Erlang simple_one_for_one supervisor does not restart child 【发布时间】:2017-05-02 14:56:43 【问题描述】:

我有一个测试模块和一个 simple_one_for_one 主管。

test.erl

-module(test).

-export([
    run/1,
    do_job/1
]).

run(Fun) ->
    test_sup:start_child([Fun]).


do_job(Fun) ->
    Pid = spawn(Fun),
    io:format("started ~p~n", [Pid]),
    ok, Pid.

test_sup.erl

-module(test_sup).
-behaviour(supervisor).

-export([start_link/0]).
-export([init/1]).
-export([start_child/1]).

start_link() ->
    supervisor:start_link(local, ?MODULE, ?MODULE, []).


init(_Args) ->
    SupFlags = #strategy => simple_one_for_one, intensity => 2, period => 20,

    ChildSpecs = [#id => test,
                    start => test, do_job, [],
                    restart => permanent,
                    shutdown => brutal_kill,
                    type => worker,
                    modules => [test]],

    ok, SupFlags, ChildSpecs.


start_child(Args) ->
    supervisor:start_child(?MODULE, Args).

我通过命令test_sup:start_link() 在 shell 中启动主管。之后我运行这个命令:test:run(fun() -> erlang:throw(err) end).我除了函数do_job重新启动2次,但它从来没有。有什么问题?

这是外壳:

1> test_sup:start_link().
ok,<0.36.0>
2> test:run(fun() -> erlang:throw(err) end).
started <0.38.0>
ok,<0.38.0>
3> 
=ERROR REPORT==== 16-Dec-2016::22:08:41 ===
Error in process <0.38.0> with exit value:
nocatch,err,[erlang,apply,2,[]]

【问题讨论】:

【参考方案1】:

重新启动子级与 simple_one_for_one 主管的定义方式相反。根据supervisor docs:

函数 delete_child/2 和 restart_child/2 对 simple_one_for_one 监管者无效,如果指定监管者使用此重启策略,则返回 error,simple_one_for_one。

换句话说,你所要求的永远不会发生。这是因为 simple_one_for_one 是为动态子代设计的,当您请求子代时通过传入额外的启动参数来动态定义这些子代。其他主管能够重新启动他们的孩子,因为启动参数是在主管中静态定义的。

基本上,这种类型的主管严格用于确保在您需要拥有动态工作人员池时整齐地关闭。

【讨论】:

以上是关于Erlang simple_one_for_one 主管不重启孩子的主要内容,如果未能解决你的问题,请参考以下文章

Erlang:supervisor(3),添加子进程

我怎么知道这是由 erlang 中的主管重新启动我的进程的最后一个周期

为啥我们需要 simple_one_for_one?

Erlang - C 和 Erlang

C 和 Erlang:Erlang 端口示例

erlang虚拟机代码运行原理