2009-08-13 5 views
2

Von dem, was ich in den Dokumenten gelesen habe, fangen gen_servers keine Exits ab. Wenn ein Prozess einen anderen Prozess mit spawn_link startet und der Kindprozess abstürzt, stürzt der Elternteil ebenfalls ab.Ich kann einen gen_server nicht durch Absturz von einem spawn_linked-Prozess zum Absturz bringen

Dies ist jedoch nicht, was ich sehe. Ich habe einen gen_server, der einen Prozess spawn_links. Ich habe eine Funktion in dem Kind Prozess wie folgt:

test(JobIsHalfDone) -> 
    case JobIsHalfDone of 
     true -> exit(test); 
     false -> ok 
    end. 

Wenn diese Funktion den Ausgang Signal sendet, erhalte ich eine Nachricht:

** Ausnahme Ausfahrt: test

Doch seine Eltern gen_server tickt ununterbrochen. Warum?

Antwort

4

Lets vergleichen Erfahrung, ich habe das folgende Verhalten, das sagt, dass es stirbt, wenn ein verknüpfter Prozess stirbt.

1> {ok, Pid} = gen_server:start(server, [], []). 
{ok,<0.33.0>} 
2> gen_server:call(Pid, nice_to_see_you). 
thanks 
3> gen_server:call(Pid, nice_to_see_you). 
thanks 
4> gen_server:call(Pid, twap).   
oh_noes 
5> gen_server:call(Pid, nice_to_see_you). 
** exception exit: {noproc,{gen_server,call,[<0.33.0>,nice_to_see_you]}} 
    in function gen_server:call/2 

Das heißt, ich habe es durch spawn_link Absturz: ein Verfahren ing, die nicht viel kostet, aber sterben, damit der Server abschaltet.

-module(server). 
-compile(export_all). 
init(_) -> 
    {ok, []}. 
handle_call(twap, _From, State) -> 
    spawn_link(fun suicidal/0), 
    {reply, oh_noes, State}; 
handle_call(_, _From, State) -> 
    {reply, thanks, State}. 
suicidal() -> 
    exit(kaboom). 

Die Tatsache, dass Sie die „*** Ausnahme Ausfahrt: Test“ scheint darauf hinzudeuten, dass Sie gen_server verwendet: START_LINK/3 aus der Schale, so dass Sie gen Server an den Shell-Prozess verknüpft ist. Das könnte zu zusätzlicher Verwirrung führen, aber nichts erklärt, warum Sie denken, dass der Server nicht gestorben ist.

+0

Ja, du hast Recht. Ich habe es nur mit einem minimalen gen_server verifiziert. Etwas anderes muss in meinem echten gen_server vor sich gehen. – mwt

+0

Ich habe es herausgefunden. Ich hatte den spawn_link lose in das gen_server-Modul platziert, anstatt ihn als Callback einzuschließen. Anscheinend bricht das die gen_server Abstraktion. – mwt

+0

Was braucht es für Sie, um eine Antwort als endgültig zu schließen? – Christian

0

Ich lag falsch, was ich denke, bringt mir einen Schritt näher zu verstehen, warum es meinen realen Server nicht tötet.

-module(crash). 
-behaviour(gen_server). 

-export([start_link/0]). 

-export([init/1, handle_call/3, handle_cast/2, handle_info/2, 
    terminate/2, code_change/3]). 

-export([crash/0]). 

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

init([]) -> 
    {ok, []}. 

crash() -> 
    gen_server:cast(?MODULE, crash). 

handle_call(_Request, _From, State) -> 
    Reply = ok, 
    {reply, Reply, State}. 

handle_cast(crash, State) -> 
    spawn_link(fun() -> 
        crash_loop(0) 
      end), 
    {noreply, State}; 
handle_cast(_Msg, State) -> 
    {noreply, State}. 

handle_info(_Info, State) -> 
    {noreply, State}. 

terminate(_Reason, _State) -> 
    ok. 

code_change(_OldVsn, State, _Extra) -> 
    {ok, State}. 

crash_loop(Counter) -> 
    case Counter =:= 10 of 
    true -> 
     exit(crash_loop); 
    false -> 
     ok 
    end, 
    timer:sleep(100), 
    crash_loop(Counter + 1). 

... und Prüfung in der Schale:

11> c(crash). 
{ok,crash} 
12> crash:start_link(). 
{ok,<0.67.0>} 
13> crash:crash(). 
ok 
14> ** exception error: crash_loop 
14> whereis(crash). 
undefined 
1

Ich denke, der Kontext Ihrer spawn_linked Prozess ist der Prozess, der den Anruf, soweit sie nicht die gen_server. Entweder spawnen Sie die Schleife im init() Callback oder führen Sie einen gen_server: call() aus und erzeugen Sie die Schleife in einem handle_call. Dann wird die Schleife mit dem Prozess verknüpft, der den gen_server ausführt.

Verwandte Themen