Erlang Supervisor无法启动
主管似乎默默无闻地开始了孩子......
这是主管
-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, []).
和gen_server
-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_server的start_link / 1显然不会被调用(使用io:fwrite进行检查)。
似乎无法找出原因...
当您注册您使用的主管时:
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, []).
您可以将Role
作为参数传递给函数。
有些东西对我来说很奇怪,你启动了调用start_socket()调用supervisor的empty_listener:start_child在主管的init函数中,此时主管没有完成它的初始化阶段。 因此,在启动儿童的主管和主管本身之间存在着一场竞赛。
我认为这段代码应该在init函数之外:
我已经完成了一个使用这种模式的应用程序,并且我有两个监督员级别:
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_child函数正在等待init的结束,没有任何东西丢失。 OTP的人比我想象的更加谨慎......
链接地址: http://www.djcxy.com/p/6511.html