2013-03-31 27 views
0

主管似乎失敗默默開始孩子......二郎主管未能start_child沒有錯誤simple_one_for_one

這裏的主管

-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是appa從來沒有打電話(用io:fwrite檢查)。

不能似乎找出爲什麼......

回答

2

當您註冊主管使用:

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作爲參數傳遞給函數。

+0

不,它不會,我們應該看到128行################# – TheSquad

+0

在啓動任何服務器之前,您得到的行打印在主管的init回調中。 – Pascal

+0

@ user601836是的,根據LearnYouSomeErlang,主管,應該開始罰款。 – TheSquad

0

東西覺得奇怪,我,您啓動empty_listener調用start_socket()調用主管:上司的初始化函數中start_child,此時主管沒有完成初始化階段。因此,在啓動兒童的主管和主管本身之間存在着一場競賽。

我認爲這個代碼應該是初始化函數外:

  • 首先開始使用主管START_LINK(端口),
  • ,當它返回調用函數start_socket()。

我已經做了其中使用這種模式的應用程序和我有2級監督員:

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傢伙已經更加謹慎比我想象...

+0

在我看來他使用的是LYSE提出的策略。我錯了嗎?我多次使用這種技術,並沒有遇到任何問題 – user601836

+0

確切地說,在http://learnyousomeerlang.com/buckets-of-sockets#sockserv-revisited找到它可以完美地與我寫的其他代碼一起工作......但是在這裏,我不知道不知道,似乎無法找到問題。 – TheSquad

+0

如user601836回答,缺少一個參數來訪問您的主管,我已經嘗試了這些修改您的代碼,它工作正常。但我真的認爲你不應該從supervisor的init函數調用start_child。即使它工作一次,你也不確定它會一直工作。如果你想避開另一個模塊,你可以在管理回調中將一條消息投射到將在init階段之後產生函數的管理器。 – Pascal