我正在学习Erlang,对下面的代码感到困惑:
-module(killing_master).
-export([start/1, loop/1]).
start(SlavesNum) ->
process_flag(trap_exit, true),
[spawn_link(fun() ->
io:format("slave ~p~n", [N]),
loop(N)
end) || N <- lists:seq(1, SlavesNum)],
spawn_link(fun() -> process_flag(trap_exit, true), init() end),
exit(normal).
init() ->
receive
{'EXIT', From, Why} -> io:format("start: (~p) exited ~p ~p~n", [self(), From, Why]);
Catch -> io:format("~p~n", [Catch])
end.
loop(SlaveNum) ->
receive
Msg -> io:format("slave #~p received ~p~n", [SlaveNum, Msg])
end.
字符串
我所期望的行为是,在主服务器退出之后,所有的从服务器也应该退出(因为spawn_link
),在这样做之前打印一条消息;而我得到的是:
1> killing_master:start(10).
slave 1
slave 2
slave 3
slave 4
slave 5
slave 6
slave 7
slave 8
slave 9
slave 10
** exception exit: normal
型
2条答案
按热度按时间webghufk1#
原因可能是主进程甚至在从进程生成之前就已经死亡,因此从进程不能监视已经退出的进程。
你可以稍微修改代码,引入一个睡眠延迟来保持主进程一段时间的活动:
字符串
然后,您应该能够看到这样的消息:
型
3yhwsihp2#
我所期望的行为是,在master退出之后,所有slave也应该退出(因为spawn_link),在这样做之前打印一条消息
另外,没有一个从进程捕获退出,所以当它们收到退出信号时不会打印消息。
字符串
并且,每个从属进程运行以下函数:
型
而
loop/1
函数也不会捕获exit。下面是一些简单的代码,您可以尝试:
型
在shell中:
型
原因可能是主人甚至在奴隶孩子出生之前就死了。
在这种情况下,我会认为
spawn_link
会返回类似{nolink, new_pid}
的内容。奇怪的是,没有办法知道链接是否成功。您可以使用以下代码确认主进程实际上已经退出:型
在shell中:
型
master()
进程的pid是<0.90.0>
,但没有列出,您可以看到slave()
正在<0.91.0>
进程中运行。或者,您可以调用:型
然而,
slave()
没有输出任何退出消息。结论是,主进程在从进程链接到它之前就退出了。因此,您的程式码会有两个问题:
1.主进程永远不会链接到从属进程。
1.即使主进程链接到从属进程,从属进程也不会捕获退出,因此它们不会打印出退出消息。