【问题标题】:terminating simple_one_for_one children individually单独终止 simple_one_for_one 孩子
【发布时间】:2012-11-04 07:02:43
【问题描述】:

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

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

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

在我的情况下,我尝试使用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), 主管: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>}}

【问题讨论】:

    标签: erlang erlang-otp


    【解决方案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
    

    【讨论】:

    • 嗨@Keynslug,你成功了,作为一个自豪的二郎菜鸟,我完全忘记了handle_info/2 的返回值。坚持使用 RPC 调用而不是发送异步消息的原因是什么?
    • @ifurrea, gen_server:cast 不是 rpc 调用,简而言之,它也是一条异步消息传递,除此之外,您遵循 gen_server 约定,并且可以确定您收到的演员来自已知发件人。与任何人都可以以非引导方式发送的普通消息相比。
    猜你喜欢
    • 2014-12-09
    • 2012-05-07
    • 2017-05-02
    • 2016-06-11
    • 2023-03-25
    • 2020-07-22
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    相关资源
    最近更新 更多