drf*_*oob 5 erlang erlang-otp erlang-supervisor
我已经实现了一个 gen_server 和 supervisor:test_server
和test_sup
. 我想从 shell/CLI 测试它们。我已经编写了它们的start_link
函数,以便它们的名称在本地注册。
我发现我可以test_server
很好地从命令行生成,但是生成的test_sup
根本不允许我与服务器进行交互。
例如,我可以test_server
通过执行来生成一个:
1> spawn(test_server, start_link, []).
<0.39.0>
2> registered().
[...,test_server,...]
Run Code Online (Sandbox Code Playgroud)
我可以与服务器交互,一切看起来都很好。
但是,如果我尝试使用 做同样的事情test_sup
,则在我的“CLI 过程”(使用registered/0
)中不会注册新名称/Pid 。我的test_server
似乎已经生成,但我无法与之交互(请参阅 Lukas Larsson 关于 SASL 的评论以了解为什么这是真的)。
我假设我在我的主管中编码了一个错误,但是这种启动主管的方法非常有效:
1> {ok, Pid}= test_sup:start_link([]).
{ok, <0.39.0>}
2> unlink(Pid).
true
3> registered().
[...,test_server,test_sup,...]
Run Code Online (Sandbox Code Playgroud)
为什么我可以生成 gen_server 但不能生成主管?
更新
我正在使用的代码可以在这篇文章中找到。我正在使用echo_server
and echo_sup
,两个非常简单的模块。
鉴于该代码,这有效:
spawn(echo_server, start_link, []).
Run Code Online (Sandbox Code Playgroud)
这不会:
spawn(echo_sup, start_link, []).
Run Code Online (Sandbox Code Playgroud)
Bernard Duggan 在Erlang 问题邮件列表中给出了这个解释:
当链接的进程以代码“正常”退出时,链接的进程不会自动终止。这就是为什么当生成进程退出时 [echo_server] 不会退出。那么主管为什么会死呢?Supervisor 模块的内部结构实际上本身是作为 gen_server 实现的,但设置了 process_flag(trap_exit, true)。这样做的结果是,当父进程终止时,terminate() 被调用(当 trap_exit 被禁用时不会发生)并且管理程序关闭。这在监督者的上下文中是有意义的,因为监督者是由监督树中的父级产生的 - 如果它在其父级关闭时没有死亡,无论什么原因,你都会有树的悬挂“分支”。