Frage

Ich arbeite durch die Erlang-Dokumentation, zu versuchen, die Grundlagen zu verstehen einen OTP gen_server und Supervisor der Einrichtung. Immer, wenn meine gen_server abstürzt, stürzt mein Vorgesetzter als auch. In der Tat, wenn ich einen Fehler in der Befehlszeile habe, stürzt mein Vorgesetzter.

erwarte ich, dass die gen_server neu gestartet werden, wenn er abstürzt. Ich erwarte, dass Fehler Kommandozeile haben kein Lager überhaupt auf meinen Server-Komponenten. Mein Vorgesetzter sollte überhaupt nicht sein abstürzt.

Der Code Ich arbeite mit einem grundlegenden „Echo-Server“, die Antworten mit dem, was Sie senden in, und ein Supervisor, der dem echo_server 5-mal pro Minute höchstens (one_for_one) wird neu gestartet. Mein 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]}]}}.

Zusammengestellt erlc *.erl verwenden, und hier ist ein Probelauf:

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>
War es hilfreich?

Lösung

Das Problem Supervisoren aus der Schale zu testen ist, dass der Überwachungsprozeß mit dem Shell-Prozess verbunden ist. Wenn gen_server Prozess abstürzt wird das Ausfahrtssignal an die Schale nach oben weitergegeben, die neu gestartet stürzt und erhalten.

Um das Problem zu merken, so etwas zu dem Supervisor zu vermeiden:

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

Andere Tipps

Ich würde Ihnen vorschlagen, debug / Spur Ihre Anwendung zu überprüfen, was los ist. Es ist sehr hilfreich für das Verständnis, wie die Dinge in OTP arbeiten.

In Ihrem Fall könnten Sie folgendes tun wollen.

Starten Sie den Tracer:

dbg:tracer().

Trace alle Funktionsaufrufe für Ihren Vorgesetzten und Ihre gen_server:

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

Überprüfen Sie, welche Meldungen die Prozesse übergeben:

dbg:p(new, m).

Sehen Sie, was Ihre Prozesse geschieht (Absturz, etc.):

dbg:p(new, p).

Weitere Informationen über Tracing:

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

http://aloiroberto.wordpress.com/2009/ 23.02 / Tracing-erlang-Funktionen /

Hope Dies kann helfen, für diese und zukünftige Situationen.

TIPP: Das gen_server Verhalten erwartet der Rückruf / 2 beenden definiert und ausgeführt werden soll;)

UPDATE: Nach der Definition des beenden / 2 der Grund des Absturzes aus der Spur erkennbar ist. Dies ist, wie es aussieht:

Wir (75) rufen Sie den Crash / 0 Funktion. Dies wird durch die gen_server empfangen (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, Problem auf dem Griff Anruf. Wir haben eine BadMatch ...

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

Die beenden Funktion aufgerufen wird: . Die Server beendet und es wird nicht registriert.

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

Der Betreuer (77) empfängt das Ausfahrtssignal vom gen_server und es macht seinen Job:

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

Nun, es versucht ... Da es geschieht, was Filippo sagte ...

Auf der anderen Seite, wenn überhaupt Neustart-Strategie aus Konsole getestet werden muss, verwendet Konsole den Supervisor und überprüfen Sie mit pman beginnen, den Prozess zu töten.

Sie würden, dass pman Auffrischungen mit gleichen Supervisor Pid sehen, aber mit unterschiedlichen Arbeitern Pids in Abhängigkeit von der MaxR und MaxT Sie in Restart-Strategie festgelegt haben.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top