Erlang Dynamic supervisor启动gen_server

时间:2011-01-30 12:25:18

标签: erlang otp supervisor

我有根管理员创建其他主管:

start_link() ->
    supervisor:start_link({local, ?MODULE}, ?MODULE, []).

init([]) ->
    RestartStrategy = {one_for_one, 5, 600},
    ListenerSup =
            {popd_listener_sup,
            {popd_listener_sup, start_link, []},
             permanent, 2000, supervisor, [popd_listener]},

    Children = [ListenerSup],

    {ok, {RestartStrategy, Children}}.

我有gen_server - 听众。当主管创建时,如何使用popd_listener_sup主管运行此gen_server?

谢谢。

1 个答案:

答案 0 :(得分:12)

根管理员

-module(root_sup).
-behaviour(supervisor).
-export([start_link/0]).
-export([init/1, shutdown/0]).

start_link() ->
     supervisor:start_link({local,?MODULE}, ?MODULE, []).

init(_Args) ->
     RestartStrategy = {one_for_one, 10, 60},
     ListenerSup = {popd_listener_sup,
          {popd_listener_sup, start_link, []},
          permanent, infinity, supervisor, [popd_listener_sup]},
     Children = [ListenerSup],
     {ok, {RestartStrategy, Children}}.    

% supervisor can be shutdown by calling exit(SupPid,shutdown)
% or, if it's linked to its parent, by parent calling exit/1.
shutdown() ->
     exit(whereis(?MODULE), shutdown).
     % or
     % exit(normal).

如果子进程是另一个主管,则子规范中的Shutdown应设置为infinity以使子树有足够的时间关闭,并且Type应设置为{{1}这就是我们所做的。

儿童主管

supervisor

此处,在子规范中,我们将-module(popd_listener_sup). -behaviour(supervisor). -export([start_link/0]). -export([init/1]). start_link() -> supervisor:start_link({local,?MODULE}, ?MODULE, []). init(_Args) -> RestartStrategy = {one_for_one, 10, 60}, Listener = {ch1, {ch1, start_link, []}, permanent, 2000, worker, [ch1]}, Children = [Listener], {ok, {RestartStrategy, Children}}. 的值设置为Shutdown。整数超时值意味着主管将通过调用2000告诉子进程终止,然后等待从子进程返回原因的退出信号。

监听

exit(Child,shutdown)

来自Erlang / OTP文档:

  

如果gen_server是a的一部分   监督树,并由其命令   主管终止,功能   -module(ch1). -behaviour(gen_server). % Callback functions which should be exported -export([init/1]). -export([handle_cast/2, terminate/2]). % user-defined interface functions -export([start_link/0]). start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). init(_Args) -> erlang:process_flag(trap_exit, true), io:format("ch1 has started (~w)~n", [self()]), % If the initialization is successful, the function % should return {ok,State}, {ok,State,Timeout} .. {ok, []}. handle_cast(calc, State) -> io:format("result 2+2=4~n"), {noreply, State}; handle_cast(calcbad, State) -> io:format("result 1/0~n"), 1 / 0, {noreply, State}. terminate(_Reason, _State) -> io:format("ch1: terminating.~n"), ok. 会   如果被Module:terminate(Reason, State)调用   以下条件适用:

     
      
  • Reason=shutdown已设置为捕获退出信号,
  •   
  • 主管子规范中定义的关机策略
      是整数超时值,而不是
      brutal_kill。
  •   

这就是我们在gen_server中调用erlang:process_flag(trap_exit, true)的原因。

样品运行

启动根管理员:

Module:init(Args)

root管理程序运行并自动启动其子进程,在我们的案例中是子监督。儿童监督员反过来开始其子过程;在我们的案例中,我们只有一个孩子1> root_sup:start_link(). ch1 has started (<0.35.0>) {ok,<0.33.0>}

让我们ch1评估正常代码:

ch1

现在有些不好的代码:

2> gen_server:cast(ch1, calc).
result 2+2=4
ok

您可能会看到儿童主管3> gen_server:cast(ch1, calcbad). result 1/0 ok ch1: terminating. =ERROR REPORT==== 31-Jan-2011::01:38:44 === ** Generic server ch1 terminating ** Last message in was {'$gen_cast',calcbad} ** When Server state == [] ** Reason for termination == ** {badarith,[{ch1,handle_cast,2}, {gen_server,handle_msg,5}, {proc_lib,init_p_do_apply,3}]} ch1 has started (<0.39.0>) 4> exit(normal). ch1: terminating. ** exception exit: normal 重新启动子进程ch1(通知popd_listener_sup)。

由于我们的shell和root管理程序是双向链接的(在根管理程序函数ch1 has started (<0.39.0>)中调用supervisor:start_link而不是supervisor:start),start_link/0导致根管理程序关闭,但它的子进程有一些时间来清理。