Erlang进程:链接进程忽略正常退出,“编译两次”后退出

时间:2014-09-04 10:46:21

标签: erlang

在Erlang中,我创建了两个彼此链接的进程。如果我从一个进程退出,那么另一个进程会忽略它,如果正常退出。可以在a link中记录此行为。

我的问题是,在编译两次相同的代码后,我可以看到第二个进程也退出了。以下是我的示例代码:

-module(exitnormal).
-export([f1/0]).

f1() ->
    X = whereis(f2) =/= undefined,
    if
        X -> exit( whereis(f2), shutdown ), timer:sleep(1);
        true -> ""
    end,
    register( f2, spawn_link( fun() -> f2() end )),
    receive
        kill -> { ok, f1 }
    end.

f2() ->
    receive
        kill -> { ok, f2 }
    end.

我用以下结果运行它:

1> c(exitnormal).
{ok,exitnormal}
2> erlang:register( f1, spawn( exitnormal, f1, [] )).
true
3> whereis(f2) ! kill, ok.
ok
4> whereis(f2).
undefined
5> whereis(f1).
<0.40.0>
6> c(exitnormal).
{ok,exitnormal}
7> whereis(f1).
<0.40.0>
8> c(exitnormal).
{ok,exitnormal}
9> whereis(f1).
undefined
10> erlang:register( f1, spawn( exitnormal, f1, [] )).
true
11> whereis(f1) ! kill, ok.
ok
12> whereis(f1).                                      
undefined
13> whereis(f2).           
<0.59.0>
14> c(exitnormal).
{ok,exitnormal}
15> c(exitnormal).
{ok,exitnormal}
16> whereis(f2).
undefined
17> 

1 个答案:

答案 0 :(得分:2)

如Erlang参考手册的the Compilation and Code Loading section所述,模块在运行的系统中可以有两种变体:“current”和“old”。当您重新加载模块时,新版本将成为“当前”版本,之前“当前”版本将变为“旧版本”,并且之前“旧”版本将被清除。清除旧版本时,任何仍然使用它的进程或对旧版本中的funs的引用都将被终止。这就是为什么在重新加载代码两次后你的进程被终止的原因。

即使模块在两个负载之间没有变化,也会发生这种情况;加载行为将无条件地触发过渡。