2012-08-23 2 views
9

私は上司の行動を理解するために簡単な例を作成しようとしている、OTPに非常に新しいです:ここでスーパーバイザはなぜ終了していますか?

は、単純なインクリメントサーバ

-module(inc_serv). 
-behaviour(gen_server). 
-export([ start/0, inc/1, stop/0 ]). 
-export([ init/1, handle_call/3, terminate/2 ]). 

start() -> 
     gen_server:start_link({ local, ?MODULE }, ?MODULE, no_args, []). 

stop() -> 
     gen_server:call(?MODULE, stop). 

inc(Num) -> 
     gen_server:call(?MODULE, { num, Num }). 

init(no_args) -> 
     io:format("~p~n", [ "Increment server started :)" ]), 
     { ok, no_state }. 

handle_call({ num, Num }, _From, no_state) -> 
     { reply, Num + 1, no_state }; 
handle_call(stop, _From, no_state) -> 
     { stop, normal, ok, no_state }. 

terminate(Reason, no_state) -> 
     io:format("~p~n", [ "Increment server stopped" ]). 

であり、私はこのことで、それが教師したいのですがモジュール:私はErlangのシェル次の手順で行ってきました。その後

-module(supervisor_inc). 
-behaviour(supervisor). 

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

start() -> 
     supervisor:start_link({ local, ?MODULE }, ?MODULE, no_args). 

init(no_args) -> 
     process_flag(trap_exit, true), 
     Supervisor_Spec = { one_for_one, 1, 1 }, 
     IncServ_Spec = { 
       inc_serv, 
       { inc_serv, start, [] }, 
       permanent, 2000, worker, [ inc_serv ] }, 
     { ok, { Supervisor_Spec, [ IncServ_Spec ] } }. 

1> 
1> c(inc_serv). 
{ok,inc_serv} 
2> 
2> c(supervisor_inc). 
{ok,supervisor_inc} 
3> 
3> supervisor_inc:start(). 
"Increment server started :)" 
{ok,<0.43.0>} 
4> 
4> inc_serv:inc(7). 
8 
5> inc_serv:inc(8). 
9 
0私は、次の試してみた。この後

(私はエラーを持っていると予想される):私が期待してきた。この後

6> inc_serv:inc(bad_arg). 
"Increment server stopped" 
"Increment server started :)" 

=ERROR REPORT==== 23-Aug-2012::19:32:06 === 
** Generic server inc_serv terminating 
** Last message in was {num,bad_arg} 
** When Server state == no_state 
** Reason for termination == 
** {badarith,[{inc_serv,handle_call,3,[{file,"inc_serv.erl"},{line,22}]}, 
       {gen_server,handle_msg,5,[{file,"gen_server.erl"},{line,588}]}, 
       {proc_lib,init_p_do_apply,3, 
         [{file,"proc_lib.erl"},{line,227}]}]} 

=ERROR REPORT==== 23-Aug-2012::19:32:06 === 
** Generic server supervisor_inc terminating 
** Last message in was {'EXIT',<0.31.0>, 
          {{{badarith, 
           [{inc_serv,handle_call,3, 
             [{file,"inc_serv.erl"},{line,22}]}, 
            {gen_server,handle_msg,5, 
             [{file,"gen_server.erl"},{line,588}]}, 
            {proc_lib,init_p_do_apply,3, 
             [{file,"proc_lib.erl"},{line,227}]}]}, 
          {gen_server,call,[inc_serv,{num,bad_arg}]}}, 
          [{gen_server,call,2, 
           [{file,"gen_server.erl"},{line,180}]}, 
          {erl_eval,do_apply,6, 
           [{file,"erl_eval.erl"},{line,576}]}, 
          {shell,exprs,7,[{file,"shell.erl"},{line,668}]}, 
          {shell,eval_exprs,7, 
           [{file,"shell.erl"},{line,623}]}, 
          {shell,eval_loop,3, 
           [{file,"shell.erl"},{line,608}]}]}} 
** When Server state == {state, 
          {local,supervisor_inc}, 
          one_for_one, 
          [{child,<0.48.0>,inc_serv, 
           {inc_serv,start,[]}, 
           permanent,2000,worker, 
           [inc_serv]}], 
          undefined,1,1, 
          [{1345,739526,107495}], 
          supervisor_inc,no_args} 
** Reason for termination == 
** {{{badarith,[{inc_serv,handle_call,3,[{file,"inc_serv.erl"},{line,22}]}, 
       {gen_server,handle_msg,5,[{file,"gen_server.erl"},{line,588}]}, 
       {proc_lib,init_p_do_apply,3, 
          [{file,"proc_lib.erl"},{line,227}]}]}, 
    {gen_server,call,[inc_serv,{num,bad_arg}]}}, 
    [{gen_server,call,2,[{file,"gen_server.erl"},{line,180}]}, 
    {erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,576}]}, 
    {shell,exprs,7,[{file,"shell.erl"},{line,668}]}, 
    {shell,eval_exprs,7,[{file,"shell.erl"},{line,623}]}, 
    {shell,eval_loop,3,[{file,"shell.erl"},{line,608}]}]} 
** exception exit: {{badarith,[{inc_serv,handle_call,3, 
             [{file,"inc_serv.erl"},{line,22}]}, 
           {gen_server,handle_msg,5, 
              [{file,"gen_server.erl"},{line,588}]}, 
           {proc_lib,init_p_do_apply,3, 
             [{file,"proc_lib.erl"},{line,227}]}]}, 
        {gen_server,call,[inc_serv,{num,bad_arg}]}} 
    in function gen_server:call/2 (gen_server.erl, line 180) 

- 私の上司はinc_servを再起動します。しかし、そうではありませんでした:

7> inc_serv:inc(8).  
** exception exit: {noproc,{gen_server,call,[inc_serv,{num,8}]}} 
    in function gen_server:call/2 (gen_server.erl, line 180) 

何が起こったのか理解してもらえますか?そして、どのように私はこれが実際に競合状態の一種であるinc_serv

おかげ

答えて

22

を再起動することができるようにするために、私の上司を書き換える必要があります。

ご存知のとおり、Erlangシェル自体は通常のErlangプロセスです。スーパーバイザをシェルから起動すると、スーパーバイザはシェルにリンクされます(supervisor:start_link/3を使用しているため)。

gen_serverプロセスを呼び出すと、そのプロセスがクラッシュします(次の"Increment server started :)"出力で確認できるように、スーパバイザによって正しく再開されます)。

しかしは、同時に、gen_server:call/2へのお電話は、同じクラッシュ(通話中にクラッシュgen_serverがgen_server:call/2機能を通じて同じクラッシュを放出する)になります。これはシェルプロセスをクラッシュさせます。シェルプロセスはスーパーバイザにリンクしていますが、同じ理由でクラッシュします(badarith)。

基本的に、管理者はgen_serverを忠実に再起動した後、シェルプロセスによってバックスラブされます。これと同じように:

 +---------(6)exit----------+ +---------(5)restart---------+ 
     |       | |       | 
     |       v |       v 
    Shell ---(1)start_link---> supervisor ---(2)start_link---> gen_server 
    |^      ^ |      ^| ^
    | |       | |       | | | 
    | |       | +---------(7)exit---------+ | | 
    | |       |         | | 
    | +-------------------------+--------------(4)exit------------+ | 
    |                 | 
    +---------------------------(3)call--------------------------------+ 

あなたのシェルでcatch inc_serv:inc(bad_arg).を呼び出すことによってこれを避けることができます偉大な答えを

90> inc_serv:inc(7).   
8 
91> catch inc_serv:inc(bad_arg). 
"Increment server stopped" 

=ERROR REPORT==== 23-Aug-2012::22:10:02 === 
** Generic server inc_serv terminating 
** Last message in was {num,bad_arg} 
** When Server state == no_state 
** Reason for termination == 
** {badarith,[{inc_serv,handle_call,3,[{file,"inc_serv.erl"},{line,20}]}, 
       {gen_server,handle_msg,5,[{file,"gen_server.erl"},{line,588}]}, 
       {proc_lib,init_p_do_apply,3, 
         [{file,"proc_lib.erl"},{line,227}]}]} 
"Increment server started :)" 
{'EXIT',{{badarith,[{inc_serv,handle_call,3, 
           [{file,"inc_serv.erl"},{line,20}]}, 
        {gen_server,handle_msg,5, 
           [{file,"gen_server.erl"},{line,588}]}, 
        {proc_lib,init_p_do_apply,3, 
           [{file,"proc_lib.erl"},{line,227}]}]}, 
        {gen_server,call,[inc_serv,{num,bad_arg}]}}} 
92> inc_serv:inc(7).    
8 
+0

感謝を! – stemm

関連する問題