主管创建多个孩子时的问题

Posted

技术标签:

【中文标题】主管创建多个孩子时的问题【英文标题】:issue when supervisor is creating more than one child 【发布时间】:2016-07-11 12:46:56 【问题描述】:

我有一个主管。我从作为 gen_server 的孩子那里得到 child_specs。我首先为一个主管 - 孩子关系写了这个。后来我想让那个主管开始生很多孩子。但是我在子 gen_server 中有一些 ets 表作为状态。因此,当主管试图创建第二个孩子时,它会抛出如下异常:

     exception exit: shutdown,
                   failed_to_start_child,bench_client2,
                       badarg,
                           [ets,new,[config,[set,named_table]],[],
                            bench_client,init,1,
                                [file,"bench_client.erl",line,59],
                            gen_server,init_it,6,
                                [file,"gen_server.erl",line,306],
                            proc_lib,init_p_do_apply,3,
                                [file,"proc_lib.erl",line,237]]

我猜测由于 ets 是共享的,当主管转到第二个孩子的 init 函数时,它已经看到了一个 ets 表,因此出现异常但不知道如何解决。不过,这只是一个猜测。

这就是我从子 gen_server 获取子规范的方式

child_specs() ->
[begin
 Name = list_to_atom(?MODULE_STRING ++ integer_to_list(Index)),
 Name, ?MODULE, start_link, [Name],
   transient, 2000, worker, [bench_client]
 end || Index <- lists:seq(1, 20)].

gen_server的init()函数是

init([]) ->
Config = ets:new(config, [set, named_table]),
Destinations = ets:new(destinations, [set, named_table]),

我是 erlang 的完全初学者,因此遇到了困难。

谢谢!

【问题讨论】:

【参考方案1】:

私人

只有所有者进程可以读取或写入表。

你能试试ets:new(config, [set, named_table, private])吗?

【讨论】:

no.. 试过但同样的错误。另外,出于好奇,如果那是私人的,其他孩子怎么能访问这张桌子?不过谢谢!【参考方案2】:

你真的需要命名的 ets 表吗?当你命名一个表时,一个 Erlang 节点中只能存在一个同名的表。去掉 ets:new/2 调用中的 named_table 选项,您将不会再收到 badarg 异常。

【讨论】:

如果 ets 表是共享的并且存在于 erlang 虚拟机中,当第一个孩子创建 ets 表时,当第二个孩子试图创建一个新表时,为什么不抛出一个例外。谢谢! @史蒂夫 如果您没有按照我的回答使用 named_table 选项,那么这两个子进程正在创建两个不同的 ets 表。例如,如果您运行erl 并连续运行两次ets:new(config, [set]).,您可以看到这一点;两次调用返回的表 ID 将不同。 很好,帮了很多忙。谢谢!

以上是关于主管创建多个孩子时的问题的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Elixir 主管中引用之前启动的进程

Erlang 主管有一个关键的孩子

如何在 Erlang/OTP 中将主管的孩子 pid 共享给另一个孩子

达到_max_restart_intensity 的主管如何只删除违规的孩子?

如何将孩子添加到 erlang 主管?

Erlang simple_one_for_one 主管不重启孩子