2016-12-12 3 views
0

私はエルラン監督について学びたいと思っています。私はhello 3秒ごとに印刷する単純なprinter processを持っています。例外が発生した場合は、printer processを再起動する必要がある管理者もいます。ここで Erlang監督は子供を再開しません

は私のコードです:

test.erl:

-module(test). 
-export([start_link/0]).  

start_link() -> 
    io:format("started~n"), 
    Pid = spawn_link(fun() -> loop() end), 
    {ok, Pid}.  

loop() -> 
    timer:sleep(3000), 
    io:format("hello~n"), 
    loop(). 

test_sup.erl:

-module(test_sup). 
-behaviour(supervisor). 

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

start_link() -> 
    supervisor:start_link({local, ?MODULE}, ?MODULE, []).  

init(_Args) -> 
    SupFlags = #{strategy => one_for_one, intensity => 1, period => 5},  
    ChildSpecs = [#{id => test, 
        start => {test, start_link, []}, 
        restart => permanent, 
        shutdown => brutal_kill, 
        type => worker, 
        modules => [test]}],  
    {ok, {SupFlags, ChildSpecs}}. 

は今、私は後にこのプログラムを実行し、test_sup:start_link().コマンドを使用して、スーパーバイザーを開始し、数秒、私は例外を発生させます。スーパーバイザがprinter processを再起動しないのはなぜですか?ここで

はシェルの出力である:あなたがerlang:error(err).を実行すると

1> test_sup:start_link(). 
started 
{ok,<0.36.0>} 
hello 
hello 
hello 
hello   
2> erlang:error(err). 

=ERROR REPORT==== 13-Dec-2016::00:57:10 === 
** Generic server test_sup terminating 
** Last message in was {'EXIT',<0.34.0>, 
          {err, 
           [{erl_eval,do_apply,6, 
            [{file,"erl_eval.erl"},{line,674}]}, 
           {shell,exprs,7, 
            [{file,"shell.erl"},{line,686}]}, 
           {shell,eval_exprs,7, 
            [{file,"shell.erl"},{line,641}]}, 
           {shell,eval_loop,3, 
            [{file,"shell.erl"},{line,626}]}]}} 
** When Server state == {state, 
          {local,test_sup}, 
          one_for_one, 
          [{child,<0.37.0>,test, 
           {test,start_link,[]}, 
           permanent,brutal_kill,worker, 
           [test]}], 
          undefined,1,5,[],0,test_sup,[]} 
** Reason for termination == 
** {err,[{erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,674}]}, 
     {shell,exprs,7,[{file,"shell.erl"},{line,686}]}, 
     {shell,eval_exprs,7,[{file,"shell.erl"},{line,641}]}, 
     {shell,eval_loop,3,[{file,"shell.erl"},{line,626}]}]} 
** exception error: err 
+0

[シェルからerlangスーパーバイザを起動できません](http://stackoverflow.com/questions/2785692/cannot-spawn-an-erlang-supervisor-from-the-shell) –

答えて

3

、あなたは、あなたのシェルを呼び出し元のプロセスを殺しています。

スーパーバイザを起動するためにstart_linkを使用していたので、それも強制終了され、ループも実行されました。

(スーパーバイザーのおかげで)シェルが自動的に再起動されますが、ループを再起動できないテストスーパーバイザを再起動する人はいません。

あなたが行う必要があり、このテストするには:

モジュールテスト中:

start_link() -> 
    Pid = spawn_link(fun() -> loop() end), 
    io:format("started ~p~n",[Pid]), 
    {ok, Pid}. 

は、プロンプトを取得します:

started <0,xx,0> 

<0,xx,0>がループのPIDで、中をあなたが呼び出すことができる殻

exit(pid(0,xx,0), err). 

は、ループのみを強制終了します。ここで

2

はあなたのファイルを作成したアーキテクチャです:

test_sup (supervisor) 
^
    | 
    v 
test (worker) 

その後、あなたの上司は、シェルでstart_link()を呼び出すことによって開始します。これにより、別の双方向リンクが作成されます。

双方向リンクの場合、一方の側が消滅し、他方の側が強制終了されます。

erlang:errorを実行すると、シェルでエラーが発生しています。

あなたのシェルはスーパーバイザにリンクされているため、Erlangは応答としてスーパーバイザを強制終了します。連鎖反応によって、あなたの労働者も殺されます。

は、私はあなたがシェルではなく、自分の作業者にエラー状態を送信するためのものだと思う:

  1. はあなたの労働者のPIDを決定します。労働者はPid上supervisor:which_children
  2. コールerlang:exit(Pid, Reason)を。
関連する問題