Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Erlang 我的主管在我试图从eshell开始时崩溃了?_Erlang_Otp_Erlang Supervisor_Gen Server - Fatal编程技术网

Erlang 我的主管在我试图从eshell开始时崩溃了?

Erlang 我的主管在我试图从eshell开始时崩溃了?,erlang,otp,erlang-supervisor,gen-server,Erlang,Otp,Erlang Supervisor,Gen Server,我对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 }, ?MO

我对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 shell中执行了以下步骤:

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
你能帮我了解发生了什么事吗?我应该如何重写我的主管,使其能够重新启动
inc\u serv


谢谢

这实际上是一种比赛状态

您可能知道,erlangshell本身是一个普通的Erlang进程。从shell启动主管时,主管将链接到shell(因为您使用了
主管:启动链接/3

调用gen_server进程时,该进程崩溃(并且由主管正确重新启动,如后续的
“增量服务器已启动:)”
输出所示)

但是与此同时,您对
gen\u server:call/2
的调用将导致相同的崩溃(在调用期间发生崩溃的gen\u服务器将通过
gen\u server:call/2
功能发出相同的崩溃)。然后,这会使链接到您的主管的shell进程崩溃,而您的主管又会因为同样的原因而崩溃(
badarith

基本上,在您的shell进程忠实地重新启动gen_服务器之后,您的主管会受到它的暗箭伤人。像这样:

       +---------(6)exit----------+    +---------(5)restart---------+
       |                          |    |                            |
       |                          v    |                            v
     Shell ---(1)start_link---> supervisor ---(2)start_link---> gen_server
     |  ^                         ^    |                         ^  |   ^
     |  |                         |    |                         |  |   |
     |  |                         |    +---------(7)exit---------+  |   |
     |  |                         |                                 |   |
     |  +-------------------------+--------------(4)exit------------+   |
     |                                                                  |
     +---------------------------(3)call--------------------------------+
您可以通过在shell中调用catch inc\u 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

这实际上是一种竞赛条件

您可能知道,erlangshell本身是一个普通的Erlang进程。从shell启动主管时,主管将链接到shell(因为您使用了
主管:启动链接/3

调用gen_server进程时,该进程崩溃(并且由主管正确重新启动,如后续的
“增量服务器已启动:)”
输出所示)

但是与此同时,您对
gen\u server:call/2
的调用将导致相同的崩溃(在调用期间发生崩溃的gen\u服务器将通过
gen\u server:call/2
功能发出相同的崩溃)。然后,这会使链接到您的主管的shell进程崩溃,而您的主管又会因为同样的原因而崩溃(
badarith

基本上,在您的shell进程忠实地重新启动gen_服务器之后,您的主管会受到它的暗箭伤人。像这样:

       +---------(6)exit----------+    +---------(5)restart---------+
       |                          |    |                            |
       |                          v    |                            v
     Shell ---(1)start_link---> supervisor ---(2)start_link---> gen_server
     |  ^                         ^    |                         ^  |   ^
     |  |                         |    |                         |  |   |
     |  |                         |    +---------(7)exit---------+  |   |
     |  |                         |                                 |   |
     |  +-------------------------+--------------(4)exit------------+   |
     |                                                                  |
     +---------------------------(3)call--------------------------------+
您可以通过在shell中调用catch inc\u 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