2012-06-20 32 views
3

我正在嘗試創建一個處理添加動態gen_servers的監督器。出於某種原因失敗的原因,我不確定是什麼。Erlang - 從監督模塊中啓動一個孩子

-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殼:

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

任何幫助/解釋/溶液理解, /秒。

+0

傳遞[]作爲start_child的第二個參數解決它。問題是我打算擴展模塊以接受傳遞給gen server的參數。這是如何完成的? – Smokie

+0

[]是參數。無論你在那裏傳遞什麼,都會被++編輯爲你在從init/1返回的通用工作模板中指定的參數 – marcelog

+0

副作用:在supervisor_mod:start_link/0中返回{ok,Pid} {ok,{ok,Pid}},因爲你的Pid變量是監督者的返回:start_link/3(這種格式是{ok,Pid}),所以你可能想要返回監督者的結果:start_link/3直接 – marcelog

回答

2

閱讀OTP Doc:如果一個策略中使用簡單策略,則可以在start_child函數中將參數作爲子項的子start_link函數的列表傳遞。

2

當您使用simple_one_for_one所有的孩子都將使用相同的ChildSpec,在init/1回調給出的這個初始化只能返回一個 ChildSpec。同樣在這種情況下,supervisor:start_child/2的第二個參數必須是一個列表,並且不是是ChildSpec。此列表是附加到默認ChildSpec中給出的參數列表的附加參數列表,它是調用子進程啓動函數時使用的組合參數列表。這就是simple_one_for_one孩子們都可以使用相同的ChildSpec,仍然可以獲得特定的參數。

就你的情況而言,由於ChildSpec中有一個空列表,並且你使用空列表調用了start_child/2,所以啓動函數的參數總數爲0。它與您的start_link/0函數的定義方式相匹配。

另一種方法是使用one_for_one並使用其自己的ChildSpec啓動每個孩子。更復雜但也更通用。

不幸的是,這種雙重使用supervisor:start_child/2使得它的論點不一致。