【发布时间】:2014-12-09 02:57:39
【问题描述】:
我有一个简单的应用程序target_interceptor,它在接收注册和注销消息时,启动或终止simple_one_for_one rpc_server_supervisor 下的工作人员。
主管rpc_server_supervisor的代码:
init([]) ->
MaxRestart = 5,
MaxTime = 3600,
{ok, {{simple_one_for_one, MaxRestart, MaxTime},
[{rbmq_rpc_server,
{rbmq_rpc_server, start_link, []},
temporary,
10000,
worker,
[rbmq_rpc_server]}]}}.
target_interceptor的注册留言:
handle_cast({register, Args}, S = #state{channel = Channel, supervisor=Sup, refs=R, qs_link = QSLinks}) ->
{Connection, QueueName, Node} = Args,
{Ok, Pid} = supervisor:start_child(Sup, [Connection, QueueName, Node]),
Ref = erlang:monitor(process, Pid),
{noreply, S#state{refs=gb_sets:add(Ref,R), qs_link=orddict:append(binary_to_list(QueueName),Pid,QSLinks)}};
target_interceptor的注销消息:
handle_cast({unregister,{QueueName}}, S = #state{supervisor = Sup, qs_link = QSLinks}) ->
Pid = orddict:fetch(QueueName,QSLinks)
case supervisor:terminate_child(Sup,Pid) of
ok -> Success = true;
Error -> io:format("Error ~p~n",[Error]),
Success = false
end,
{noreply, S#state{qs_link=orddict:erase(QueueName,QSLinks)}}
我的 Erlang 版本是:R15B01
第一个问题是在处理注册操作时,元组 {OK, Pid} = {error, };尽管它表明出现问题,但 Pid 57 上的 gen_server rbmq_rpc_server 工作正常并响应消息。为什么start_child函数的返回值错误?出了什么问题?
第二个问题是在处理注销操作时,即使我引用 Pid 而不是 ChildID,supervisor:terminate_child(Sup,Pid) 也会返回 {error,simple_one_for_one)。为什么会有这样的行为?我如何动态地单独终止主管的孩子?
编辑:
target_interceptor 和 rpc_server_supervisor 均由 rbmq_sup_sup 主管监督:
init({Nodeid, Node}) ->
MaxRestart = 1,
MaxTime = 3600,
{ok, {{rest_for_one, MaxRestart, MaxTime},
[{server,
{target_interceptor, start_link, [target, self(), {Nodeid, Node}]},
permanent,
5000,
worker,
[target_interceptor]}]}}.
编辑: rpc_server_supervisor 在 target_interceptor init() 函数中被调用(这里是 rbmq_sup_sup supervisor):
handle_info({start_worker_supervisor, Sup}, S = #state{}) ->
{ok, Pid} = supervisor:start_child(Sup, ?SPEC),
link(Pid),
{noreply, S#state{sup=Pid}};
-define(SPEC,
{rpc_server_sup,
{rpc_server_sup, start_link, []},
temporary,
10000,
supervisor,
[rpc_server_sup]}).
【问题讨论】: