Erlang - 从主管模块启动一个孩子

时间:2012-06-20 13:03:24

标签: erlang otp

我正在尝试创建一个处理添加动态gen_servers的主管。有些事情是失败的,我不确定是什么。

-module(supervisor_mod).
-behaviour(supervisor).

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

start_link() ->
    Pid=supervisor:start_link({local, ?MODULE} , ?MODULE, []),
    {ok,Pid}.

init(_Args) ->
    {ok, {{simple_one_for_one, 10, 60},
          [{example_proc, {example_proc, start_link, []},
            permanent, brutal_kill, worker, [example_proc]}]}}.

add_child(Name)->                                                                        
    supervisor:start_child(supervisor_mod,
                           {example_proc, {example_proc, start_link, []},
                            permanent, brutal_kill, worker, [example_proc]}).

-module(example_proc).
-behaviour(gen_server).

-export([start_link/0]).
-export([init/1, handle_call/3, handle_cast/2]).

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

init(Args) ->
    io:format("~p (~p) started...~n", [Args, self()]),
    {ok, []}.

handle_call(alloc, From, State) ->
    {reply, From, State}.

handle_cast({free, _Ch}, State) ->
    {noreply, State}.

在erl shell中:

Eshell V5.8.2  (abort with ^G)
1> supervisor_mod:start_link().
{ok,{ok,<0.33.0>}}
2> supervisor_mod:add_child(aa).
{error,{'EXIT',{badarg,[{erlang,apply,
                                [example_proc,start_link,
                                 {example_proc,{example_proc,start_link,[]},
                                               permanent,brutal_kill,worker,
                                               [example_proc]}]},
                        {supervisor,do_start_child_i,3},
                        {supervisor,handle_call,3},
                        {gen_server,handle_msg,5},
                        {proc_lib,init_p_do_apply,3}]}}}

感谢任何帮助/解释/解决方案, /秒。

2 个答案:

答案 0 :(得分:2)

如果一个策略只有一个,请阅读OTP Doc:,在start_child函数中,您可以将参数作为子项的子start_link函数的列表传递。

答案 1 :(得分:2)

当您使用simple_one_for_one时,所有孩子都将使用相同的ChildSpec,init/1回调中提供的那个和此初始化只能返回一个 ChildSpec。同样在这种情况下,supervisor:start_child/2的第二个参数必须是一个列表,一个ChildSpec。此列表是附加参数的列表,它附加到默认ChildSpec中给出的参数列表中,它是在调用子函数的start函数时使用的组合参数列表。这就是simple_one_for_one个孩子都可以使用相同的ChildSpec并且仍然能够获得特定参数的方式。

在您的情况下,由于ChildSpec中有一个空列表,并且您使用空列表调用start_child/2,启动函数的参数总数为0。这与您start_link/0函数的定义方式相匹配。

另一种方法是使用one_for_one并使用自己的ChildSpec启动每个孩子。更复杂但也更通用。

不幸的是,supervisor:start_child/2的这种双重用法使其参数不一致。

相关问题