Erlang 我的主管在我试图从eshell开始时崩溃了?
我对OTP非常陌生,我试图创建一个简单的示例来了解主管的行为: 下面是简单的增量服务器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
-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