从我在文档中读到的内容来看,gen_servers并没有捕获退出。此外,我的理解是,如果进程使用spawn_link启动另一个进程,并且子进程崩溃,则父进程崩溃。
然而,这不是我所看到的。我有一个gen_server,用于spawn_links一个进程。我在子进程中设置了一个函数,如下所示:
test(JobIsHalfDone) ->
case JobIsHalfDone of
true -> exit(test);
false -> ok
end.
当此功能发出退出信号时,我收到一条消息:
**例外退出:测试
然而它的父级gen_server仍然正确。为什么呢?
答案 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