Simple_one_for_one can only be terminated if appointed SHUTDOWN strategy to brutal_kill?

StackOverflow https://stackoverflow.com/questions/16693922

  •  30-05-2022
  •  | 
  •  

Question

The supervisor is an OTP behavior.

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]}}.

Above code will invoke child's terminate method.

But if I change the brutal_kill to an integer timeout (e.g. 6000), the terminate method was never invoked.

I see an explanation in the Erlang document:

The dynamically created child processes of a simple-one-for-one supervisor are not explicitly killed, regardless of shutdown strategy, but are expected to terminate when the supervisor does (that is, when an exit signal from the parent process is received).

But I cannot fully understand. Is it said that exit(Pid, kill) can terminate a simple_one_for_one child spec while exit(Pid, shutdown) can't ?

===================================update====================================

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.

Both mod_zytm_sup and mod_zytm_room_sup are a part of a system supervision tree, mod_zytm_sup invoke mod_zytm_room_sup to create or close mod_zytm_room process.

Was it helpful?

Solution

Sorry I've got wrong result.

To make it clear:

  1. brutal_kill strategy kill child process immediately.
  2. The terminate method will be invoked if the simple_one_for_one's shutdown strategy is an integer timeout. The child must declare process_flag(trap_exit, true) in its init callback.

FYI, Manual on Erlang doc:

If the gen_server is part of a supervision tree and is ordered by its supervisor to terminate, this function will be called with Reason=shutdown if the following conditions apply:

the gen_server has been set to trap exit signals, and the shutdown strategy as defined in the supervisor's child specification is an integer timeout value, not brutal_kill.

OTHER TIPS

The dynamically created child processes of a simple-one-for-one supervisor are not explicitly killed, regardless of shutdown strategy, but are expected to terminate when the supervisor does (that is, when an exit signal from the parent process is received).

Note that this is no longer true. Since Erlang/OTP R15A, dynamic children are explicitly terminated as per the shutdown strategy.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top