2

我有一个由 gen_servers 作为临时子级组成的监督树,它们的寿命很短。每个孩子在清理和终止时都会收到一条消息。

受我从tinymq项目中阅读的代码的启发,有一个控制器进程可以保存这些孩子的 Pid 的字典。

在他们的情况下,他们使用 max_age 设置和一些我不太明白的代码来过期他们的频道。

在我的情况下,我在进行一些清理后尝试使用supervisor:terminate_child(Sup, Pid),如下所示:

孩子本身在控制器上执行 RPC:

fs_outbound_controller:deallocate_me(UUID, self());

控制器:

deallocate_me(UUID, Pid) ->
    gen_server:cast(?SERVER, {deallocate_me, UUID, Pid}).

handle_cast({deallocate_me, UUID, Pid}, #state{dict = Uuid2Pid} = State) ->
    NewDict = dict:erase(UUID, Uuid2Pid),
    supervisor:terminate_child(fs_outbound_extn_sup, Pid),
    error_logger:info_msg("Successfully deallocated ~p", [UUID]),
    {noreply, State#state{dict=NewDict}}.

我观察到的问题是 ERROR 记录器报告了关于 gen_server 终止返回值的崩溃?

** Reason for termination == 
** {bad_return_value,ok}

感谢您的帮助。

编辑

我做了其他事情,我将对 deallocate_me 的调用从 RPC 移动到从子级到控制器的消息。认为也许孩子对控制器进行 RPC 调用,而这反过来又终止了孩子,这导致了一些返回问题。处理程序保持不变

handle_info({deallocate_me, UUID, Pid}, #state{dict = Uuid2Pid} = State) -> NewDict = dict:erase(UUID, Uuid2Pid), supervisor:terminate_child(fs_outbound_extn_sup, Pid), error_logger:info_msg("成功释放~ p", [UUID]), {noreply, State#state{dict=NewDict}}。

但现在我仍然得到:

** Reason for termination == 
** {bad_return_value,{deallocate_me,"49d9f7cb-62d3-4c3f-abf1-a19848967a9a",
                                    <0.50.0>}}
4

1 回答 1

1

在我看来

fs_outbound_controller:deallocate_me(UUID, self());

被称为handle_call/3,handle_cast/2或中的最后一条语句handle_info/2。这些正在期待类似的东西{reply, ...}{noreply, ...}或者{stop, ...}你可能知道的。

请记住,gen_server:cast/2总是返回ok并且ServerPid ! Message总是返回Message自身。这就是为什么第一次告诉你{bad_return_value, ok},第二次告诉你{bad_return_value, MessageSent}

在你的情况下,我会坚持下去gen_server:cast,只是在错误的调用之后放置正确的返回值:

fs_outbound_controller:deallocate_me(UUID, self()),
{noreply, State}; %% strongly depends on what your logic there is
于 2012-11-15T18:40:22.353 回答