2

スーパーバイザー:

-module(mod_guild_chapter_sup).
-include("guild_dungeon.hrl").

-behaviour(supervisor).

%% API
-export([start_link/0]).

%% Supervisor callbacks
-export([init/1]).

-define(SERVER, ?MODULE).

%%%===================================================================
%%% API functions
%%%===================================================================

%%--------------------------------------------------------------------
%% @doc
%% Starts the supervisor
%%
%% @spec start_link() -> {ok, Pid} | ignore | {error, Error}
%% @end
%%--------------------------------------------------------------------
start_link() ->
    supervisor:start_link({local, ?SERVER}, ?MODULE, []).

%%%===================================================================
%%% Supervisor callbacks
%%%===================================================================

%%--------------------------------------------------------------------
%% @private
%% @doc
%% Whenever a supervisor is started using supervisor:start_link/[2,3],
%% this function is called by the new process to find out about
%% restart strategy, maximum restart frequency and child
%% specifications.
%%
%% @spec init(Args) -> {ok, {SupFlags, [ChildSpec]}} |
%%                     ignore |
%%                     {error, Reason}
%% @end
%%--------------------------------------------------------------------
init([]) ->
    RestartStrategy = simple_one_for_one,
    MaxRestarts = 1000,
    MaxSecondsBetweenRestarts = 3600,

    SupFlags = {RestartStrategy, MaxRestarts, MaxSecondsBetweenRestarts},

    Restart = transient,
    Shutdown = 60000,
    Type = worker,

    ModGuildChapter = {'guild_chapter', {'mod_guild_chapter', start_link, []},
                       Restart, Shutdown, Type, ['mod_guild_chapter']},

    {ok, {SupFlags, [ModGuildChapter]}}.

子供:

-module(mod_guild_chapter).

-record(state, {}).

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

init([GuildId, ChapterId]) ->
    case condition() of
        true -> ignore;
        false -> {ok, #state{})
    end.

...omit other callbacks...

supervisor:which_children(mod_guild_chapter_sup):

[{undefined,<0.9635.0>,worker,[mod_guild_chapter]},
 {undefined,<0.9539.0>,worker,[mod_guild_chapter]},
 {undefined,<0.9475.0>,worker,[mod_guild_chapter]},
 {undefined,<0.9493.0>,worker,[mod_guild_chapter]},
 {undefined,<0.9654.0>,worker,[mod_guild_chapter]},
 {undefined,undefined,worker,[mod_guild_chapter]},
 {undefined,<0.9658.0>,worker,[mod_guild_chapter]},
 {undefined,<0.9517.0>,worker,[mod_guild_chapter]},
 {undefined,<0.9567.0>,worker,[mod_guild_chapter]}]

受信時の例外shutdown:

2015-07-03 14:56:33 =CRASH REPORT====
  crasher:
    initial call: mod_guild_chapter:init/1
    pid: <0.9475.0>
    registered_name: []
    exception exit: {{function_clause,[{supervisor,'-monitor_dynamic_children/2-fun-1-',[undefined,[100062,10003],{{set,3,16,16,8,80,48,{[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},{{[],[],[],[],[],[],[],[<0.9658.0>],[],[],[<0.9517.0>],[],[<0.9567.0>],[],[],[]}}},{dict,0,16,16,8,80,48,{[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},{{[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]}}}}],[{file,"supervisor.erl"},{line,992}]},{dict,fold_bucket,3,[{file,"dict.erl"},{line,441}]},{dict,fold_seg,4,[{file,"dict.erl"},{line,437}]},{dict,fold_segs,4,[{file,"dict.erl"},{line,433}]},{supervisor,terminate_dynamic_children,3,[{file,"supervisor.erl"},{line,959}]},{gen_server,terminate,6,[{file,"gen_server.erl"},{line,719}]},{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,239}]}]},[{gen_server,terminate,6,[{file,"gen_server.erl"},{line,744}]},{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,239}]}]}
    ancestors: [mod_guild_chapter_sup,mod_guild_sup,yg_sup,<0.82.0>]
    messages: []
    links: []
    dictionary: []
    trap_exit: true
    status: running
    heap_size: 1598
    stack_size: 27
    reductions: 6586
  neighbours:

ご覧のとおり、そこにあってはundefinedならない pid があります。

ドキュメントにはこれを説明する 2 つの場所がありますが、それらの間に矛盾があります。

  1. temporary返されても子が存在しない場合、子の指定はスーパーバイザによって保持されますignore

start は、子プロセスを開始するために使用される関数呼び出しを定義します。apply(M,F,A) として使用される module-function-arguments タプル {M,F,A} でなければなりません。

start 関数は、子プロセスを作成してリンクする必要があり、{ok,Child} または {ok,Child,Info} を返す必要があります。ここで、Child は子プロセスの pid であり、Info はスーパーバイザーによって無視される任意の用語です。

start 関数は、何らかの理由で子プロセスを開始できない場合にも無視を返すことができます。その場合、子の仕様は (一時的な子でない限り) スーパーバイザーによって保持されますが、存在しない子プロセスは無視されます。

  1. simple_one_for_onestart 時に戻った場合、pid はスーパーバイザに追加されませんignore

子プロセス開始関数が無視を返す場合、子仕様がスーパーバイザーに追加され (スーパーバイザーが simple_one_for_one スーパーバイザーでない限り、以下を参照)、pid が未定義に設定され、関数は {ok,undefined} を返します。

simple_one_for_one スーパーバイザーの場合、子プロセス開始関数が ignore を返すと、関数は {ok,undefined} を返し、子はスーパーバイザーに追加されません。

私はその文書に混乱した。transientクラッシュ時に子が再起動する必要があるため、再起動戦略を選択します。しかし、ここでこの例外を回避するにはどうすればよいですか?

4

1 に答える 1

0

わかりました、あなたの質問をもう一度読みました。ドキュメントによると、子の start 関数で ignore を返すと、この子は開始されません。simple_one_for_one スーパーバイザーの場合、子の仕様も保持されません (これは、スーパーバイザーの開始時に保存される仕様が 1 つしかない論理的な原因です)。これは、次の行を意味します。

{undefined,undefined,worker,[mod_guild_chapter]},

子プロセスが開始されていないことを示しているだけです。したがって、プロセスが例外の理由になることはありません。クラッシュ レポートは、クラッシュしたプロセスの pid を示します。これは <0.9475.0> です。which_children の戻りリストで見つけることができます。これは、クラッシュの原因を調べるために検査するプロセスです。

于 2015-07-06T08:29:16.517 に答える