Simple_one_for_one 是否只能在将 SHUTDOWN 策略指定为brittle_kill 时终止?

goo*_*nsu 6 erlang erlang-otp

主管是一种 OTP 行为。

init([]) ->
    RoomSpec = {mod_zytm_room, {mod_zytm_room, start_link, []},
                transient, brutal_kill, worker, [mod_zytm_room]},
    {ok, {{simple_one_for_one, 10, 10000}, [RoomSpec]}}.
Run Code Online (Sandbox Code Playgroud)

上面的代码将调用孩子的terminate方法。

但是,如果我将 更改brutal_kill为整数超时(例如 6000),terminate则永远不会调用该方法。

我在 Erlang 文档中看到了一个解释:

无论关闭策略如何,动态创建的简单一对一监督者的动态创建的子进程都不会被明确杀死,但预计会在监督者这样做时终止(即,当收到来自父进程的退出信号时)。

但我不能完全理解。是不是说exit(Pid, kill)可以终止simple_one_for_one子规范而exit(Pid, shutdown)不能?

======================================更新============== ======================

mod_zytm_room_sup.erl

-module(mod_zytm_room_sup).

-behaviour(supervisor).

-export([start_link/0, init/1, open_room/1, close_room/1]).

start_link() -> 
    supervisor:start_link({local, ?MODULE}, ?MODULE, []).

init([]) ->
    RoomSpec = {mod_zytm_room, {mod_zytm_room, start_link, []},
                transient, brutal_kill, worker, [mod_zytm_room]},
    {ok, {{simple_one_for_one, 10, 10000}, [RoomSpec]}}.

open_room(RoomId) ->
    supervisor:start_child(?MODULE, [RoomId]).

close_room(RoomPid) ->
    supervisor:terminate_child(?MODULE, RoomPid).
Run Code Online (Sandbox Code Playgroud)

mod_zytm_room.erl

-module(mod_zytm_room).

-behaviour(gen_server).

-export([start_link/1]).

-export([init/1, handle_cast/2, handle_info/2, handle_call/3, code_change/3, terminate/2]).

start_link(RoomId) ->
    gen_server:start_link(?MODULE, [RoomId], []).

init([RoomId]) ->
    {ok, []}.

terminate(_, _) ->
    error_logger:info_msg("~p terminated:~p", [?MODULE, self()]),
    ok.

...other methods ommited.
Run Code Online (Sandbox Code Playgroud)

mod_zytm_sup.erl

-module(mod_zytm_sup).

-behaviour(gen_server).

-export([start_link/0]).

-export([init/1, handle_cast/2, handle_info/2, handle_call/3, code_change/3, terminate/2]).

start_link() ->
    gen_server:start_link(?MODULE, [], []).

init([]) ->
    {ok, []}.

%% invoked by an erlang:send_after event.
handle_info({'CLOSE_ROOM', RoomPid}, State) ->
    mod_zytm_room_sup:close_room(RoomPid),
    {noreply, State}.

...other methods ommited.
Run Code Online (Sandbox Code Playgroud)

这两个mod_zytm_supmod_zytm_room_sup是一个系统的监督树的一部分,mod_zytm_sup调用mod_zytm_room_sup创建或接近mod_zytm_room过程。

goo*_*nsu 4

抱歉,我得到了错误的结果。

为了明确起见:

  1. brutal_kill策略立即杀死子进程。
  2. terminate如果 simple_one_for_one 的关闭策略是整数超时,则将调用该方法。子级必须process_flag(trap_exit, true)在其init回调中声明。

仅供参考,Erlang 文档手册:

如果 gen_server 是监督树的一部分,并且被其监督者命令终止,则如果满足以下条件,则将使用 Reason=shutdown 调用此函数:

gen_server 已设置为捕获退出信号,并且主管子规范中定义的关闭策略是整数超时值,而不是brutal_kill。

  • **注意** `terminate` 回调预计不会实际终止子进程。它的目的是在服务器之后进行任何必要的清理,并且当它返回时,行为本身将结束进程。并执行指定的任何日志记录等。 (2认同)