Domanda

Sto lavorando attraverso la documentazione Erlang, cercando di capire le basi della creazione di un gen_server OTP e supervisore. Ogni volta che il mio gen_server si blocca, il mio supervisore si blocca pure. In effetti, ogni volta che ho un errore sulla linea di comando, il mio supervisore si blocca.

mi aspetto il gen_server per essere riavviato quando si blocca. Mi aspetto errori di linea di comando per avere alcuna incidenza su componenti mio server. Il mio supervisore non deve essere blocca a tutti.

Il codice sto lavorando con un "server echo" di base che le risposte con tutto ciò che si invia in, e un supervisore che riavviare l'echo_server 5 volte al minuto al massimo (one_for_one). Il mio codice:

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

compilato utilizzando erlc *.erl, ed ecco un esempio di esecuzione:

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>
È stato utile?

Soluzione

Il problema testare vigilanza dalla shell è che il processo supervisore è legata al processo shell. Quando il processo gen_server blocca il segnale di uscita si propaga fino al guscio che blocca e ottenere riavviato.

Per evitare il problema aggiungere qualcosa di simile al supervisore:

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

Altri suggerimenti

vorrei suggerire di di debug / trace l'applicazione per controllare cosa sta succedendo. E 'molto utile per capire come funzionano le cose in OTP.

Nel tuo caso, si potrebbe desiderare di fare quanto segue.

Avviare il tracciante:

dbg:tracer().

Trace tutte le chiamate di funzione per il supervisore e la vostra gen_server:

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

Controllare che i messaggi i processi sono di passaggio:

dbg:p(new, m).

vedere cosa sta succedendo ai processi (incidente, ecc):

dbg:p(new, p).

Per ulteriori informazioni sull'analisi:

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

http://aloiroberto.wordpress.com/2009/ 02/23 / tracing erlang-funzioni /

Spero che questo può aiutare per questo e situazioni future.

Suggerimento: Il comportamento gen_server prevede la richiamata terminare / 2 da definire e esportate;)

UPDATE: Dopo la definizione del terminare / 2 il motivo del crollo è evidente dalla traccia. Questo è come appare:

(75) chiamare la funzione di 0 / crash. Questo viene ricevuto dal 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)

Uh, problema sulla chiamata manico. Abbiamo un badmatch ...

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

La funzione terminare si chiama . Le uscite server e ottiene non registrati.

(<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

Il supervisore (77) riceve il segnale di uscita dal gen_server e fa il suo lavoro:

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

Bene, prova ... Dal momento che accade quello che ha detto Filippo ...

D'altra parte, se non del tutto riavvio strategia deve essere testato dal di dentro console, console funzione per iniziare il supervisore e verificare con pman di uccidere il processo.

Si vedrebbe che rinfresca Pman con un'unica autorità di vigilanza Pid ma con diversi PID dei lavoratori a seconda del MaxR e MAXT impostati nel riavvio-strategia.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top