Question

Je travaille dans la documentation Erlang, en essayant de comprendre les bases de la mise en place d'un Bureau du Procureur gen_server et le superviseur. Chaque fois que mon gen_server tombe en panne, mon superviseur plante aussi bien. En fait, chaque fois que j'ai une erreur sur la ligne de commande, mon superviseur accidents.

Je pense que le gen_server à redémarrer quand il se bloque. Je me attends des erreurs de ligne de commande pour avoir aucune incidence sur mes composants du serveur. Mon superviseur ne doit pas être du tout s'écraser.

Le code que je travaille avec un « serveur d'écho » de base que les réponses à tout ce que vous envoyez, et un superviseur qui redémarrera le echo_server 5 fois par minute au maximum (one_for_one). Mon code:

echo_server.erl

-module(echo_server).
-behaviour(gen_server).

-export([start_link/0]).
-export([echo/1, crash/0]).
-export([init/1, handle_call/3, handle_cast/2]).

start_link() ->
    gen_server:start_link({local, echo_server}, echo_server, [], []).

%% public api
echo(Text) ->
    gen_server:call(echo_server, {echo, Text}).
crash() ->
    gen_server:call(echo_server, crash)..

%% behaviours
init(_Args) ->
    {ok, none}.
handle_call(crash, _From, State) ->
    X=1,
    {reply, X=2, State}.
handle_call({echo, Text}, _From, State) ->
    {reply, Text, State}.
handle_cast(_, State) ->
    {noreply, State}.

echo_sup.erl

-module(echo_sup).
-behaviour(supervisor).
-export([start_link/0]).
-export([init/1]).

start_link() ->
    supervisor:start_link(echo_sup, []).
init(_Args) ->
    {ok,  {{one_for_one, 5, 60},
       [{echo_server, {echo_server, start_link, []},
             permanent, brutal_kill, worker, [echo_server]}]}}.

erlc *.erl en utilisant Compilé et est ici une course exemple:

Erlang R13B01 (erts-5.7.2) [source] [smp:2:2] [rq:2] [async-threads:0] [kernel-p
oll:false]

Eshell V5.7.2  (abort with ^G)
1> echo_sup:start_link().
{ok,<0.37.0>}
2> echo_server:echo("hi").
"hi"
3> echo_server:crash().   

=ERROR REPORT==== 5-May-2010::10:05:54 ===
** Generic server echo_server terminating 
** Last message in was crash
** When Server state == none
** Reason for termination == 
** {'function not exported',
       [{echo_server,terminate,
            [{{badmatch,2},
              [{echo_server,handle_call,3},
               {gen_server,handle_msg,5},
               {proc_lib,init_p_do_apply,3}]},
             none]},
        {gen_server,terminate,6},
        {proc_lib,init_p_do_apply,3}]}

=ERROR REPORT==== 5-May-2010::10:05:54 ===
** Generic server <0.37.0> terminating 
** Last message in was {'EXIT',<0.35.0>,
                           {{{undef,
                                 [{echo_server,terminate,
                                      [{{badmatch,2},
                                        [{echo_server,handle_call,3},
                                         {gen_server,handle_msg,5},
                                         {proc_lib,init_p_do_apply,3}]},
                                       none]},
                                  {gen_server,terminate,6},
                                  {proc_lib,init_p_do_apply,3}]},
                             {gen_server,call,[echo_server,crash]}},
                            [{gen_server,call,2},
                             {erl_eval,do_apply,5},
                             {shell,exprs,6},
                             {shell,eval_exprs,6},
                             {shell,eval_loop,3}]}}
** When Server state == {state,
                            {<0.37.0>,echo_sup},
                            one_for_one,
                            [{child,<0.41.0>,echo_server,
                                 {echo_server,start_link,[]},
                                 permanent,brutal_kill,worker,
                                 [echo_server]}],
                            {dict,0,16,16,8,80,48,
                                {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],
                                 []},
                                {{[],[],[],[],[],[],[],[],[],[],[],[],[],[],
                                  [],[]}}},
                            5,60,
                            [{1273,79154,701110}],
                            echo_sup,[]}
** Reason for termination == 
** {{{undef,[{echo_server,terminate,
                          [{{badmatch,2},
                            [{echo_server,handle_call,3},
                             {gen_server,handle_msg,5},
                             {proc_lib,init_p_do_apply,3}]},
                           none]},
             {gen_server,terminate,6},
             {proc_lib,init_p_do_apply,3}]},
     {gen_server,call,[echo_server,crash]}},
    [{gen_server,call,2},
     {erl_eval,do_apply,5},
     {shell,exprs,6},
     {shell,eval_exprs,6},
     {shell,eval_loop,3}]}
** exception exit: {{undef,
                        [{echo_server,terminate,
                             [{{badmatch,2},
                               [{echo_server,handle_call,3},
                                {gen_server,handle_msg,5},
                                {proc_lib,init_p_do_apply,3}]},
                              none]},
                         {gen_server,terminate,6},
                         {proc_lib,init_p_do_apply,3}]},
                    {gen_server,call,[echo_server,crash]}}
     in function  gen_server:call/2
4> echo_server:echo("hi").
** exception exit: {noproc,{gen_server,call,[echo_server,{echo,"hi"}]}}
     in function  gen_server:call/2
5>
Était-ce utile?

La solution

Le test superviseurs problème de la coquille est que le processus de superviseur est lié au processus de la coquille. Lorsque le processus de gen_server bloque le signal de sortie se propage jusqu'à la coquille qui tombe en panne et se redémarrée.

Pour éviter l'ajout de problème quelque chose comme ceci au superviseur:

start_in_shell_for_testing() ->
    {ok, Pid} = supervisor:start_link(echo_sup, []),
    unlink(Pid).

Autres conseils

Je vous suggère de debug / trace votre application pour vérifier ce qui se passe. Il est très utile pour comprendre comment les choses fonctionnent dans OTP.

Dans votre cas, vous voudrez peut-être faire ce qui suit.

Démarrer le traceur:

dbg:tracer().

Trace tous les Appels de fonction pour votre superviseur et votre gen_server:

dbg:p(all,c).
dbg:tpl(echo_server, x).
dbg:tpl(echo_sup, x).

Vérifiez quels messages les processus passent:

dbg:p(new, m).

Voir ce qui se passe à vos processus (accident, etc.):

dbg:p(new, p).

Pour plus d'informations sur le traçage:

http://www.erlang.org/doc/man/dbg.html

http://aloiroberto.wordpress.com/2009/ 02/23 / traçage-Erlang-fonctions /

Espérons que cela peut aider à cet effet et des situations futures.

Indice: Le comportement gen_server attend le rappel se terminent / 2 à définir et exportées;)

Mise à jour: Après la définition du terminate / 2 la raison de l'accident est évidente de la trace. Voici comment il ressemble:

(75) appeler l'accident / 0 fonction. Ceci est reçu par le gen_server (78).

(<0.75.0>) call echo_server:crash()
(<0.75.0>) <0.78.0> ! {'$gen_call',{<0.75.0>,#Ref<0.0.0.358>},crash}
(<0.78.0>) << {'$gen_call',{<0.75.0>,#Ref<0.0.0.358>},crash}
(<0.78.0>) call echo_server:handle_call(crash,{<0.75.0>,#Ref<0.0.0.358>},none)

Euh, problème sur l'appel de la poignée. Nous avons BadMatch ...

(<0.78.0>) exception_from {echo_server,handle_call,3} {error,{badmatch,2}}

La fonction fin est appelée . Les sorties du serveur et il obtient non enregistré.

(<0.78.0>) call echo_server:terminate({{badmatch,2},
 [{echo_server,handle_call,3},
  {gen_server,handle_msg,5},
  {proc_lib,init_p_do_apply,3}]},none)
(<0.78.0>) returned from echo_server:terminate/2 -> ok
(<0.78.0>) exit {{badmatch,2},
 [{echo_server,handle_call,3},
  {gen_server,handle_msg,5},
  {proc_lib,init_p_do_apply,3}]}
(<0.78.0>) unregister echo_server

Le contrôleur (77) reçoit le signal de sortie du gen_server et il fait son travail:

(<0.77.0>) << {'EXIT',<0.78.0>,
                      {{badmatch,2},
                       [{echo_server,handle_call,3},
                        {gen_server,handle_msg,5},
                        {proc_lib,init_p_do_apply,3}]}}
(<0.77.0>) getting_unlinked <0.78.0>
(<0.75.0>) << {'DOWN',#Ref<0.0.0.358>,process,<0.78.0>,
                      {{badmatch,2},
                       [{echo_server,handle_call,3},
                        {gen_server,handle_msg,5},
                        {proc_lib,init_p_do_apply,3}]}}
(<0.77.0>) call echo_server:start_link()

Eh bien, il essaie ... Comme il arrive ce que Filippo a dit ...

Par contre, si tout redémarrage stratégie doit être testé à partir de la console, la console d'utilisation pour démarrer le superviseur et vérifier avec pman pour tuer le processus.

Vous verriez que rafraîchi pman avec la même superviseur, mais avec différentes Pid Pids des travailleurs en fonction de la MaxR et MaxT que vous avez définies dans la stratégie redémarrage.

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