无法使gen_server从spawn_linked进程崩溃中崩溃

时间:2009-08-13 22:15:37

标签: erlang

从我在文档中读到的内容来看,gen_servers并没有捕获退出。此外,我的理解是,如果进程使用spawn_link启动另一个进程,并且子进程崩溃,则父进程崩溃。

然而,这不是我所看到的。我有一个gen_server,用于spawn_links一个进程。我在子进程中设置了一个函数,如下所示:

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

当此功能发出退出信号时,我收到一条消息:

**例外退出:测试

然而它的父级gen_server仍然正确。为什么呢?

3 个答案:

答案 0 :(得分:4)

让我们比较经验,我有以下行为,表示当链接的流程死亡时它会死亡。

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

也就是说,我通过spawn_link让它崩溃了:一个不会太多但很快死的过程,让服务器失效。

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

您看到“*** exception exit:test”的事实似乎表明您使用了shell中的gen_server:start_link / 3,因此您将gen服务器链接到shell进程。这可能引入额外的混乱,但没有解释为什么你会认为服务器没有死。

答案 1 :(得分:1)

我认为你的spawn_linked进程的上下文是进行调用的进程,而不是gen_server。要么在init()回调中生成循环,要么执行gen_server:call()并在handle_call中生成循环。然后循环将链接到运行gen_server的进程。

答案 2 :(得分:0)

我错了,我想让我更接近理解为什么它不会杀死我的真实服务器。

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

...并在shell中进行测试:

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