Erlang Supervisor无法启动\u child,没有错误简单的\u one\u for \u one

Erlang Supervisor无法启动\u child,没有错误简单的\u one\u for \u one,erlang,erlang-supervisor,gen-server,Erlang,Erlang Supervisor,Gen Server,主管似乎在悄悄地启动孩子时失败了 这是主管 -behaviour(supervisor). -export([start_socket/0, init/1, start_link/1]). -define(SSL_OPTIONS, [{active, once}, {backlog, 128}, {reuseaddr, true}, {packet, 0},

主管似乎在悄悄地启动孩子时失败了

这是主管

-behaviour(supervisor).
-export([start_socket/0, init/1, start_link/1]).

-define(SSL_OPTIONS, [{active, once},
                      {backlog, 128},
                      {reuseaddr, true},
                      {packet, 0},
                      {cacertfile, "./ssl_key/server/gd_bundle.crt"},
                      {certfile, "./ssl_key/server/cert.pem"},
                      {keyfile, "./ssl_key/server/cert.key"},
                      {password, "**********"}
                     ]).

start_link(Port) ->
    Role = list_to_atom(atom_to_list(?MODULE) ++ lists:flatten(io_lib:format("~B", [Port]))),
    supervisor:start_link({local, Role}, ?MODULE, [Port]).

init([Port]) ->
    R = ssl:listen(Port, ?SSL_OPTIONS),
    LSocket = case R of
                  {ok, LSock} ->
                      LSock;
                  Res ->
                      io:fwrite("gateway_sup Error: ~p~n", [Res])
              end,
    spawn_link(fun empty_listeners/0),
    ChildSpec = [{socket,
                  {gateway_serv, start_link, [LSocket]},
                  temporary, 1000, worker, [gateway_serv]}
                ],
    {ok, {{simple_one_for_one, 3600, 3600},
          ChildSpec
         }}.

empty_listeners() ->
    io:fwrite("---------------------- empty_listeners~n"),
    [start_socket() || _ <- lists:seq(1,128)],
    ok.

start_socket() ->
    io:fwrite("++++++++++++++++++++++ start_socket~n"),
    supervisor:start_child(?MODULE, []).
-module(gateway_serv).

-behaviour(gen_server).
-export([start_link/1, init/1, handle_call/3, handle_cast/2, handle_info/2, code_change/3, terminate/2]).

start_link(LSocket) ->
io:fwrite("#################~n"),
    gen_server:start_link(?MODULE, [LSocket], []).

init([LSocket]) ->
io:fwrite("/////////////////~n"),
    gen_server:cast(self(), accept),
    {ok, #client{listenSocket=LSocket, pid=self()}}.

handle_cast(accept, G = #client{listenSocket=LSocket}) ->
    {ok, AcceptSocket} = ssl:transport_accept(LSocket),
    gateway_sup:start_socket(),
    case ssl:ssl_accept(AcceptSocket, 30000) of
    ok ->
        timer:send_after(10000, closingSocket),
        ssl:setopts(AcceptSocket, [{active, once}, {mode, list}, {packet, 0}]),
        {noreply, G#client{listenSocket=none, socket=AcceptSocket}};
    {error, _Reason} ->
        {stop, normal, G}
    end;
handle_cast(_, G) ->
    {noreply, G}.
显然从未调用gen\u服务器的start\u链接/1(使用io:fwrite进行检查)。

似乎无法找出原因…

对我来说有些奇怪,您启动空的\u侦听器调用start\u socket(),调用supervisor:start\u child,在supervisor的init函数中,此时supervisor没有完成初始化阶段。因此,在要求主管启动孩子的过程和主管本身之间存在着竞争

我认为这段代码应该在init函数之外:

  • 首先使用start_链路(端口)启动监控程序
  • 当它返回时,调用函数start_socket()。
我已经完成了一个使用此模式的应用程序,我有两个级别的主管:

main supervisor (one_for_all strategy)
|                         |
|                         |
v                         v
application   ------->    supervisor (simple_one_for_one strategy)
server      start_child   worker factory
                          |
                          |
                          v*
                          many children
编辑: 忘掉这个比赛条件吧


我在init函数结束之前做了一个引入延迟的测试,我看到start_子函数在等待init结束时没有丢失任何东西。检察官办公室的人比我想象的还要谨慎

注册您使用的主管时:

Role = list_to_atom(atom_to_list(?MODULE) ++ lists:flatten(io_lib:format("~B", [Port]))),
因此,当你打电话时:

start_socket() ->
    io:fwrite("++++++++++++++++++++++ start_socket~n"),
    supervisor:start_child(?MODULE, []).
您正在呼叫一个不存在的主管

你应该称之为:

supervisor:start_child(Role, []).

您可以将
角色
作为参数传递给函数。

在我看来,他正在使用LYSE中提出的策略。我错了吗?我曾多次使用这种技术,但没有遇到任何问题,我发现它可以与我编写的其他代码完美地配合使用。。。但在这里,我不知道,似乎找不到问题。正如user601836所回答的,缺少一个参数来访问您的主管,我已经用这些修改尝试了您的代码,效果很好。但我真的认为,您不应该从主管的init函数调用start_child。即使它能工作一次,你也不确定它是否能一直工作。如果您想避免使用另一个模块,您可以向主管强制转换一条消息,该消息将在强制转换回调中的初始化阶段之后生成函数。在启动任何服务器之前,您得到的行在主管的初始化回调中打印。@user601836是的,根据主管LearnyYouSomeerlang的说法,应该可以正常启动。看到了吗!接受它!非常感谢。我快疯了+1.