Erlang - Starting a child from the supervisor module

白昼怎懂夜的黑 提交于 2019-12-07 08:17:15

问题


I'm trying to create a supervisor which handles adding dynamic gen_servers. for a reason something is failing and I'm not really sure what.

-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]}).

and

-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}.

in 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}]}}}

Any help/explanation/solution is appreciated, /s.


回答1:


Read OTP Doc: in case of simple one for one strategy, in start_child function you can pass arguments as a list for the child start_link function of the child.




回答2:


When you use simple_one_for_one all the children will use the same ChildSpec, the one given in the init/1 callback and this initialisation can only return one ChildSpec. Also in this case the second argument to supervisor:start_child/2 must be a list and NOT a ChildSpec. This list is a list of extra arguments which is appended to the argument list given in the default ChildSpec and it is this combined argument list which is used when calling the child's start function. This is how the simple_one_for_one children all can use the same ChildSpec and still can get in specific arguments to them.

In your case as there was an empty list in the ChildSpec and you called start_child/2 with an empty list the total number of arguments to the start function was 0. Which matched how your start_link/0 function is defined.

An alternative is in your case to use one_for_one and start each child with its own ChildSpec. More complex but also more versatile.

Unfortunately this dual use of supervisor:start_child/2 has made it inconsistent in its arguments.



来源:https://stackoverflow.com/questions/11120207/erlang-starting-a-child-from-the-supervisor-module

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!