Erlang 无法使gen_服务器从与spawn_链接的进程崩溃中崩溃

Erlang 无法使gen_服务器从与spawn_链接的进程崩溃中崩溃,erlang,Erlang,从我在文档中读到的内容来看,gen_服务器不会捕获出口。此外,我的理解是,如果一个进程使用spawn_链接启动另一个进程,并且子进程崩溃,那么父进程也会崩溃 然而,这不是我所看到的。我有一个gen_服务器,可以生成一个进程链接。我在子进程中设置了一个函数,如下所示: test(JobIsHalfDone) -> case JobIsHalfDone of true -> exit(test); false -> ok end.

从我在文档中读到的内容来看,gen_服务器不会捕获出口。此外,我的理解是,如果一个进程使用spawn_链接启动另一个进程,并且子进程崩溃,那么父进程也会崩溃

然而,这不是我所看到的。我有一个gen_服务器,可以生成一个进程链接。我在子进程中设置了一个函数,如下所示:

test(JobIsHalfDone) -> 
    case JobIsHalfDone of
        true -> exit(test);
        false -> ok
    end.
当此函数发送退出信号时,我收到一条消息:

**异常退出:测试


然而,它的父代gen_服务器一直在运行。为什么?

让我们比较一下经验,我有以下行为,即当链接进程死亡时,它确实会死亡

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

您看到***异常退出:测试的事实似乎表明您使用了shell中的gen_server:start_link/3,以便gen server链接到shell进程。这可能会带来更多的困惑,但无法解释为什么你会认为服务器没有死。

我错了,我想这让我更进一步了解为什么它没有杀死我真正的服务器

-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).
…并在壳牌公司进行测试:

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

我认为与spawn_链接的进程的上下文是发出调用的进程,而不是gen_服务器。要么在init回调中生成循环,要么执行gen_server:call并在handle_调用中生成循环。然后循环将链接到运行gen_服务器的进程。

是的,你说得对。我只是自己用一个最小的gen_服务器验证了一下。我真正的gen_服务器中肯定有别的事情发生了。我知道了。我将spawn_链接放在gen_服务器模块中,而不是将其作为回调。很明显,这打破了gen_服务器的抽象概念。那么,你需要做什么才能最终得出答案呢?我认为我在这方面没有足够的声誉。
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