Frage

Ich habe einen Root-Supervisor, der einen anderen Supervisor erstellt:

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}}.

Und ich habe gen_server - Listener.Wie kann ich diesen gen_server mit dem popd_listener_sup-Supervisor ausführen, wenn der Supervisor erstellt wurde?

Danke.

War es hilfreich?

Lösung

Root-Supervisor
-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).

Wenn der untergeordnete Prozess ein anderer Supervisor ist, sollte Shutdown in der untergeordneten Spezifikation auf infinity gesetzt werden, damit der Teilbaum ausreichend Zeit zum Herunterfahren hat, und Type sollte auf supervisor gesetzt werden, und das haben wir getan.

Kinderbetreuer
-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}}.

Hier setzen wir in einer untergeordneten Spezifikation den Wert von Shutdown auf 2000. Ein ganzzahliger Timeout-Wert bedeutet, dass der Supervisor den untergeordneten Prozess durch Aufrufen von exit(Child,shutdown) zum Beenden auffordert und dann auf ein Exit-Signal wartet, dessen Grund vom untergeordneten Prozess zurückgesetzt wird.

Listener
-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.

Aus der Erlang / OTP-Dokumentation:

Wenn der gen_server Teil von a ist Überwachungsbaum und wird von seiner bestellt Supervisor zu beenden, die Funktion Module:terminate(Reason, State) wird mit Reason=shutdown aufgerufen werden, wenn Es gelten folgende Bedingungen:

  • Der gen_server wurde so eingestellt, dass Ausgangssignale abgefangen werden, und
  • die Abschaltstrategie, wie sie in der untergeordneten Spezifikation des Supervisors definiert ist
    ist ein ganzzahliger Timeout-Wert, nicht
    brutal_kill.

    Deshalb haben wir erlang:process_flag(trap_exit, true) in Module:init(Args) genannt.

    Probelauf

    Starten des Root-Supervisors:

    1> root_sup:start_link().
    ch1 has started (<0.35.0>)
    {ok,<0.33.0>}
    

    Der Root-Supervisor wird ausgeführt und startet automatisch seine untergeordneten Prozesse, in unserem Fall den untergeordneten Supervisor. Der Child Supervisor wiederum startet seine untergeordneten Prozesse. In unserem Fall haben wir nur ein Kind, ch1.

    Lassen Sie ch1 den normalen Code auswerten:

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

    Nun ein schlechter Code:

    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
    

    Wie Sie vielleicht sehen, wurde der ch1 des untergeordneten Prozesses vom popd_listener_sup des untergeordneten Supervisors neu gestartet (beachten Sie den ch1 has started (<0.39.0>)).

    Da unsere Shell und unser Root-Supervisor bidirektional miteinander verbunden sind (rufen Sie supervisor:start_link auf, nicht supervisor:start in der Root-Supervisor-Funktion start_link/0), führte exit(normal) zum Herunterfahren des Root-Supervisors, aber die untergeordneten Prozesse hatten einige Zeit zum Bereinigen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top