【问题标题】:Erlang - Starting a child from the supervisor moduleErlang - 从主管模块启动一个孩子
【发布时间】:2012-06-22 15:04:24
【问题描述】:

我正在尝试创建一个主管来处理添加动态 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 外壳中:

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

感谢任何帮助/解释/解决方案, /s.

【问题讨论】:

  • 将 [] 作为第二个参数传递给 start_child 解决了这个问题。重点是我计划扩展模块以接受传递给 gen 服务器的参数。这是怎么做到的?
  • [] 是参数。无论您在那里传递什么,都将被 ++'ed 到您在从 init/1 返回的通用工作模板中指定的参数中
  • 旁注:在 supervisor_mod:start_link/0 您返回 {ok, Pid} 最终表示 {ok, {ok, Pid}},因为您的 Pid 变量是主管的返回: start_link/3 (已经采用 {ok, Pid} 格式),因此您可能只想直接返回 supervisor:start_link/3 的结果

标签: erlang erlang-otp


【解决方案1】:

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

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

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

不幸的是,supervisor:start_child/2 的这种双重使用使它的论点不一致。

【讨论】:

    【解决方案2】:

    如果是简单的一对一策略,请阅读OTP Doc:,在 start_child 函数中,您可以将参数作为子级 start_link 函数的列表传递。

    【讨论】:

      猜你喜欢
      • 2017-05-02
      • 2014-06-17
      • 2012-11-11
      • 2011-06-18
      • 2017-09-20
      • 2017-05-02
      • 2014-12-09
      • 2023-03-16
      • 2015-01-22
      相关资源
      最近更新 更多