Question

Je superviseur racine qui crée un autre superviseur:

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

Et j'ai gen_server - auditeur. Comment puis-je exécuter ce gen_server avec le superviseur de popd_listener_sup, quand le superviseur créé?

Merci.

Était-ce utile?

La solution

superviseur racine

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

Si le processus de l'enfant est un autre superviseur, Shutdown dans la spécification de l'enfant doit être réglé sur infinity pour donner la sous-arborescence suffisamment de temps à l'arrêt, et Type doit être réglé sur supervisor, et que ce que nous avons fait.

superviseur enfant

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

Ici, dans un cahier des charges de l'enfant, nous avons mis en valeur Shutdown à 2000. Un moyen de délai d'attente entier que le superviseur dit que le processus de l'enfant de mettre fin en appelant exit(Child,shutdown) puis attendre un signal de sortie avec le dos d'arrêt raison du processus de l'enfant.

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.

De la documentation Erlang / OTP:

Si la gen_server fait partie d'un arbre de surveillance et est commandé par son superviseur de mettre fin, la fonction volonté de Module:terminate(Reason, State) être appelé avec Reason=shutdown si les conditions suivantes:

  • le gen_server a été fixé à des signaux de sortie du piège, et
  • la stratégie d'arrêt tel que défini dans la spécification de enfant
    du superviseur est une valeur de délai d'entier, et non pas
    brutal_kill.

Voilà pourquoi nous appelions erlang:process_flag(trap_exit, true) dans Module:init(Args).

run échantillon

Démarrage du superviseur racine:

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

superviseur racine est exécuté et démarre automatiquement ses processus enfants, superviseur des enfants dans notre cas. superviseur de l'enfant à son tour commence ses processus enfants; nous avons un seul enfant dans notre cas, ch1.

faire la ch1 Let évaluer le code normal:

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

Maintenant, certains mauvais 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

Comme vous pouvez le voir processus enfant ch1 a été repris par le superviseur de l'enfant popd_listener_sup (avis ch1 has started (<0.39.0>)).

Depuis notre coquille et le superviseur racine sont bidirectionnellement liées (appel supervisor:start_link, non supervisor:start dans la fonction superviseur racine start_link/0), exit(normal) a donné lieu à l'arrêt du superviseur racine, mais ses processus enfants ont un peu de temps à nettoyer.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top