Pregunta

Estoy trabajando a través de la documentación de Erlang, tratando de comprender los fundamentos de la creación de un gen_server OTP y el supervisor. Cada vez que mi gen_server se estrella, mi supervisor se estrella también. De hecho, cada vez que tengo un error en la línea de comandos, mi supervisor bloquea.

espero que la gen_server que se reinicie cuando se rompe. Espero errores de línea de comandos para tener ninguna incidencia en mis componentes del servidor. Mi supervisor no debe ser fallando en absoluto.

El código que estoy trabajando es un "servidor de eco" básica que responde con lo que envíe, y un supervisor que se reinicie el echo_server 5 veces por minuto como máximo (one_for_one). Mi código:

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

Compilado usando erlc *.erl, y he aquí una muestra de ejecución:

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>
¿Fue útil?

Solución

El problema pruebas de los supervisores de la cáscara es que el proceso supervisor está vinculado al proceso de shell. Cuando el proceso gen_server se bloquea la señal de salida se propaga hasta la cáscara que se bloquea y se les reinicia.

Para evitar el problema de añadir algo como esto al supervisor:

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

Otros consejos

Yo sugeriría usted a depuración / trace su aplicación para comprobar lo que está pasando. Es muy útil en la comprensión de cómo funcionan las cosas en OTP.

En su caso, es posible que desee hacer lo siguiente.

Inicio del trazador:

dbg:tracer().

Traza todas las llamadas de función para su supervisor y su gen_server:

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

Comprobar los mensajes que los procesos están pasando:

dbg:p(new, m).

Vea lo que le está pasando a sus procesos (accidente, etc.):

dbg:p(new, p).

Para obtener más información acerca del seguimiento:

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

http://aloiroberto.wordpress.com/2009/ 02/23 / rastreo-erlang-funciones /

Espero que esto puede ayudar para esto y situaciones futuras.

PISTA: El comportamiento gen_server está esperando la devolución de llamada terminan / 2 a definir y exportados;)

ACTUALIZACIÓN: Después de la definición de la terminan / 2 el motivo del accidente es evidente a partir de la traza. Esto es lo que parece:

(75) llame a la función 0 / accidente. Esta es recibida por el 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, un problema en la llamada mango. Tenemos un BadMatch ...

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

La función de terminar se llama . El servidor se cierra y se vuelve no registrado.

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

El Supervisor (77) recibe la señal de salida de la gen_server y hace su trabajo:

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

Bueno, trata ... Como ocurre lo dijo Filippo ...

Por otro lado, en todo caso reinicio-estrategia tiene que ser probado desde el interior de la consola, el uso de la consola para iniciar el supervisor y comprobar con pman para matar el proceso.

vería que refresca con pman mismo supervisor Pid pero con diferentes PIDs de los trabajadores, dependiendo de la MaxR y MaxT que ha establecido en el reinicio-estrategia.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top