Erlang: superviseur (3), l'ajout d'un processus enfant
-
27-10-2019 - |
Question
Où puis-je trouver par exemple sur la façon d'ajouter des processus enfants à un superviseur dynamique existant ( simple_one_for_one
stratégie redémarrage)?
La solution
Je l'ai fait quelques recherches, et au-dessous est ce que j'ai.
Tout d'abord, c'est un module de rappel échantillon d'un superviseur:
-module(root_sup).
-behaviour(supervisor).
-export([start_link/0]).
-export([init/1]).
start_link() ->
{ok, Pid} = supervisor:start_link({local, ?MODULE},
?MODULE, []),
{ok, Pid}.
init(_Args) ->
RestartStrategy = {simple_one_for_one, 10, 60},
ChildSpec = {ch1, {ch1, start_link, []},
permanent, brutal_kill, worker, [ch1]},
Children = [ChildSpec],
{ok, {RestartStrategy, Children}}.
Et c'est un module de rappel d'un enfant qui sera ajouté à l'arbre suprervision dynamiquement:
-module(ch1).
-behaviour(gen_server).
% Callback functions which should be exported
-export([init/1]).
-export([handle_cast/2]).
% user-defined interface functions
-export([start_link/0]).
start_link() ->
gen_server:start_link(?MODULE, [], []).
init(_Args) ->
io:format("ch1 has started (~w)~n", [self()]),
% If the initialization is successful, the function
% should return {ok,State}, {ok,State,Timeout} ..
{ok, ch1State}.
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}.
Voici comment nous commençons généralement le superviseur:
1> ch_sup:start_link().
{ok,<0.33.0>}
Maintenant, nous allons commencer notre premier processus enfant:
2> {ok, Child1Pid} = supervisor:start_child(ch_sup, []).
ch1 has started (<0.35.0>)
{ok,<0.35.0>}
Vous pouvez commencer dynamiquement les processus de l'enfant; Commençons un autre enfant:
3> {ok, Child2Pid} = supervisor:start_child(ch_sup, []).
ch1 has started (<0.37.0>)
{ok,<0.37.0>}
Vous pouvez voir que nos processus ne commencent (note les deux dernières):
4> erlang:processes().
[<0.0.0>,<0.2.0>,<0.4.0>,<0.5.0>,<0.7.0>,<0.8.0>,<0.9.0>,
<0.10.0>,<0.11.0>,<0.12.0>,<0.13.0>,<0.14.0>,<0.15.0>,
<0.16.0>,<0.17.0>,<0.18.0>,<0.19.0>,<0.20.0>,<0.21.0>,
<0.22.0>,<0.23.0>,<0.24.0>,<0.25.0>,<0.26.0>,<0.27.0>,
<0.31.0>,<0.33.0>,<0.35.0>,<0.37.0>]
Maintenant, nous allons faire notre premier processus enfant faire quelque chose:
5> gen_server:cast(Child1Pid, calc).
result 2+2=4
ok
Jusqu'à présent, si bon. Maintenant, nous allons faire notre premier enfant d'évaluer certains mauvais code:
6> gen_server:cast(Child1Pid, calcbad).
result 1/0
ok
7>
=ERROR REPORT==== 10-Feb-2011::01:32:15 ===
** Generic server <0.35.0> terminating
** Last message in was {'$gen_cast',calcbad}
** When Server state == ch1State
** Reason for termination ==
** {'function not exported',
[{ch1,terminate,
[{badarith,
[{ch1,handle_cast,2},
{gen_server,handle_msg,5},
{proc_lib,init_p_do_apply,3}]},
ch1State]},
{gen_server,terminate,6},
{proc_lib,init_p_do_apply,3}]}
ch1 has started (<0.42.0>)
7>
Dans le rapport, vous pouvez voir que la division par zéro a provoqué une exception et le processus a pris fin. Mais le superviseur prend soin de lui et commence immédiatement à un autre processus enfant (note la dernière ligne).
Nous pouvons vérifier pour vous assurer que l'autre processus de l'enfant que nous avons commencé est déjà encore en vie (note <0.37.0>
):
7> erlang:processes().
[<0.0.0>,<0.2.0>,<0.4.0>,<0.5.0>,<0.7.0>,<0.8.0>,<0.9.0>,
<0.10.0>,<0.11.0>,<0.12.0>,<0.13.0>,<0.14.0>,<0.15.0>,
<0.16.0>,<0.17.0>,<0.18.0>,<0.19.0>,<0.20.0>,<0.21.0>,
<0.22.0>,<0.23.0>,<0.24.0>,<0.25.0>,<0.26.0>,<0.27.0>,
<0.31.0>,<0.33.0>,<0.37.0>,<0.42.0>]
8>
On peut même faire faire quelque chose pour nous:
8> gen_server:cast(Child2Pid, calc).
result 2+2=4
9>
Voici les pages de manuel Erlang vous voulez lire: