2012-08-23 30 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" ]). 

है और मैं इसे इस की देखरेख करना चाहते हैं मॉड्यूल:

-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 ] } }. 

कि मैं erlang खोल अगले चरणों में किया जाता करने के बाद:

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 

इस मैं अगले प्रयास करने के बाद (के रूप में मैं उम्मीद मैं त्रुटि मिल गया है):

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

संबंधित मुद्दे