2

gen_serverと呼ばれるIを生成するスーパーバイザーを作成しましたtimer_server。このtimer_serverのタスクの1つは、登録を管理timer:send_intervalし、特定の間隔でpidにメッセージを送信するために呼び出すことです。

gen_serverしかし、私が呼んでいるの初期段階では、timer:send_interval私はロックアップを取得していました。ドキュメントによると、タイマー:関数はすぐに戻るので、これは非常に厄介でした。

名前を変更gen_serverすると、record_timer_serverこの問題は解決しました。私の質問は2つあります:

  1. アプリケーションの起動時に呼び出されたtimer_serverときにすでにプロセスが存在するのに、なぜ登録済みプロセスを作成できるのですか?timer:start()
  2. timer_server一度開始すると、関数を使用して呼び出している場合、この関数が名前の検出に不一致を引き起こさないのはなぜsend_intervalですか?

コードは必要ないと思いますが、必要に応じて更新して追加することができます。

4

1 に答える 1

3

これは、timer:send_interval の呼び出しでハングする次のことを実行するだけで再作成できます。

1> register(timer_server, self()).
true
2> timer:send_interval(5000, self(), hello).

これが失敗している間...

1> timer:send_interval(5000, self(), hello).
{ok,{interval,#Ref<0.0.0.32>}}
2> register(timer_server, self()).
** exited: {badarg,[{erlang,register,[timer_server,<0.30.0>]},

そのため、timer への最初の呼び出しは timer_server というプロセスを開始しようとし、最初にこの名前を使用するとハングするようです。

timer.erl がハングする理由については、次のとおりです。

ensure_started() ->
    case whereis(timer_server) of
        undefined -> 
            C = {timer_server, {?MODULE, start_link, []}, permanent, 1000, 
                worker, [?MODULE]}
            supervisor:start_child(kernel_safe_sup, C),  % kernel_safe_sup
            ok;
        _ -> ok
    end.

これは問題なく返され、続いて gen_server:timer_server への呼び出しが行われます。プロセスは、それ自体が応答するのを待ってスタックします。

于 2009-02-01T09:05:34.380 に答える