1

私が作成したプロセスのスーパーバイザーを作成しようとしています。私はこれをしばらくの間調査しましたが役に立たなかったので、誰かが助けてくれることを願っています.

これは課題用であるため、使用しなければならないインターフェースに特定の制限があるため、リストを使用した例や、Erlang サイトのより精巧な OTP の例も知っていますが、これらは適切ではありません。問題を示すために、アプリケーションから抜粋した例を提供しました。

通常の理由で終了した任意のワーカーを再起動しようとしています。ワーカー プロセスは次のとおりです。

-module(my_mod).

-export([start/1, init/1]).

start(Pid)->
  {ok, spawn_link(?MODULE, init, [Pid])}.

init(Pid) ->
  register(Pid, self()),
  io:format("Started ~p~n",[Pid]),
  loop().

loop() ->
  receive stop -> exit(byebye) end.

スーパーバイザーでは、ワーカーを追跡して再起動するために ETS タブを使用しています。スーパーバイザーは次のようになります。

-module(my_sup).

-export([start_link/0, init/1, add_item/1, remove_item/1]).


start_link() ->
  spawn(?MODULE, init, [self()]).

init(Pid) ->
  process_flag(trap_exit, true),
  register(?MODULE, Pid),
  ets:new(?MODULE, [set, named_table, public]),
  loop().

add_item(Pid) ->
  ets:insert(?MODULE, {Pid}),
  my_mod:start(Pid),
  {ok, Pid}.

remove_item(Pid) ->
  ets:delete(?MODULE, [Pid]).

loop() ->
  io:format("Looping ~n"),
  receive
    {'EXIT', Pid, _Reason} ->
      remove_item(Pid),
      add_item(Pid)
  end.

だから私はここで何かをしていると思います.my_modはスーパーバイザにリンクされているので、終了シグナルが通知されます.スーパーバイザはtrap_exitを設定して、スーパーバイザがシグナルを処理する機会を得る必要があります. しかし、** 例外 exit: stop がスローされるだけで、なぜそうなのかわかりませんか?

私のテストケースは次のとおりです。

1> c(my_sup), c(my_mod), my_sup:start_link().
Looping 
<0.42.0>
2> my_sup:add_item(a). 
Started a
{ok,a}
3> a ! stop .
** exception exit: byebye

誰かが私を正しい方向に向けることができますか?

4

2 に答える 2

3

シェルadd_item/1では、スーパーバイザー プロセス内ではなく、シェル プロセス内で呼び出しが発生します。つまり、スーパーバイザーは新しく追加されたプロセスにリンクされていませんが、シェルはリンクされています。代わりにadd_item/1、スーパーバイザー プロセスにメッセージを送信して新しいワーカーを起動するように指示し、スーパーバイザー ループを変更してその新しいメッセージを処理し、そこからワーカーを起動する必要があります。

于 2014-12-06T19:46:52.290 に答える
1

わかりました。Steve V が指摘したように、私の問題は、add_item/1 を呼び出すときに、実際にはスーパーバイザではなくシェル プロセスにリンクしていたことです。次の解決策を見つけました。既存の Pid を追加しようとすると問題が発生するという問題がまだいくつかありますが、最初の質問に対する適切な解決策です。my_mod は次のように変更されました。

-module(my_mod).

-export([start/1, init/1]).

start(Name)->
  {ok, spawn_link(?MODULE, init, [Name])}.

init(Name) ->
  register(Name, self()),
  io:format("Started ~p~n",[Name]),
  loop().

loop() ->
  receive 
    exit -> exit(kill);
    stop -> exit(graceful)
  end. 

および監督者は次のように修正しました。

-module(my_sup).

-export([start_link/0, init/0, add_item/1, remove_item/1]).

start_link() -> register(?MODULE, spawn(?MODULE, init, [])).

init() ->
  process_flag(trap_exit, true),
  ets:new(?MODULE, [set, named_table, public]), loop().

add_item(Name) -> ?MODULE ! {add_item, Name}.

update_item(Name, Pid) -> ?MODULE ! {update_item, Name, Pid}.

remove_item(Name) -> ?MODULE ! {remove_item, Name}.

 loop() ->
   io:format("Looping ~n"),
   receive
     {'EXIT', Pid, graceful} ->
       io:format("~p exiting gracefully. ~n", [Pid]),
       loop();
     {'EXIT', Pid, Reason} ->
      io:format("ERROR: ~p, ~p ~n", [Pid, Reason]),
       [[Name, Id]] = ets:select(my_sup, [{{'$1', '$2'}, [{'==', '$2', pid_to_list(Pid)}], [['$1', '$2']]}]),
       update_item(Pid, Name), loop();
     {add_item, Name} ->
       {ok, Pid} = my_mod:start(Name),
       ets:insert(?MODULE, {Name, pid_to_list(Pid)}),
       loop();
      {update_item, Pid, Name} ->
       {ok, NewPid} = my_mod:start(Name),
       ets:update_element(?MODULE, Name, {2, pid_to_list(NewPid)}),
       loop();
      {remove_item, Name} ->
        ets:delete(?MODULE, Name),
        Name ! stop, loop()
   end.

スーパーバイザから my_mod メソッドを呼び出していることに注意してください。my_mod で spawn_link が呼び出されると、シェルではなくスーパーバイザにリンクされます。また、インターフェイス メソッドのアリティを壊さない他のアクションを実行できる受信ループからコマンドを渡すことで、規定のスーパーバイザー インターフェイス add_item/1、remove_item/1 を強制することもできます。私は以下でテストしました:

1> c(my_sup), c(my_mod), my_sup:start_link(), my_sup:add_item(a), my_sup:add_item(b), observer:start().
Looping 
Started a
Looping 
Started b
ok
2> my_sup:remove_item(a).
Looping 
<0.43.0> exiting gracefully. 
{remove_item,a}
Looping 
3> b ! exit .
ERROR: <0.44.0>, kill 
Looping 
exit
Looping 
Started b

ああ、私はまた、なぜ私が電話をかけられなかったのかについて、ぐるぐる回るのに時間を費やしました

exit(whereis(Pid), normal).

これは次のように説明されます。

「... exit(Pid, normal) の呼び出し。プロセスは引数として通常の理由でリモートで強制終了できないため、このコマンドは何も役に立ちません。」

http://learnyousomeerlang.com/errors-and-processes

これが他の人に役立つことを願っています...

于 2014-12-07T20:22:22.463 に答える