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.