6

主管是一种 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]}}.

上面的代码将调用孩子的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).

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.

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.

两者mod_zytm_supmod_zytm_room_sup都是系统监督树的一部分,mod_zytm_sup调用mod_zytm_room_sup以创建或关闭 mod_zytm_room 进程。

4

2 回答 2

4

对不起,我得到了错误的结果。

说清楚:

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

仅供参考,Erlang 文档手册:

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

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

于 2013-05-22T19:21:16.033 回答
1

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

请注意,这不再适用。从 Erlang/OTP R15A 开始,动态子节点会根据关闭策略显式终止。

于 2020-05-31T17:13:07.847 回答