学习 supervisor 时的问题,被重启的 gen_server 出错,提示 exception exit: {noproc,{gen_server,call,[gs1,{g,a}]}}。

100 views
Skip to first unread message

gamexg hzly

unread,
May 26, 2012, 10:59:58 PM5/26/12
to ec...@googlegroups.com, erlang...@googlegroups.com
新人学习 erlang ,建了一个简单的 k-v gen_server ,用supervisor 启动它,结果 gen_server
出错重启后,调用 gen_server 提示exception exit:
{noproc,{gen_server,call,[gs1,{g,a}]}}。
看记录显示 gen_server 已经重启了啊,而且没有重启失败的提示。
请问是什么原因造成重启后的 gen_server 调用失败啊?


错误:
Eshell V5.9.1 (abort with ^G)
1> code:add_patha("D:\\Dropbox\\eclipse\\workspace\\test1\\src").
true
2> sup1:start().
sup1 init...
init...
{ok,<0.34.0>}
3> gs1:s(a,1).
ok
4> gs1:g(a).
{ok,1}
5> gs1:k(). %% 使 gen_server 出错
init...

=ERROR REPORT==== 27-May-2012::10:15:10 ===
** Generic server gs1 terminating
** Last message in was k
** When Server state == {state,{dict,1,16,16,8,80,48,
{[],[],[],[],[],[],[],[],[],[],[],[],[],
[],[],[]},
{{[],
[[a|1]],
[],[],[],[],[],[],[],[],[],[],[],[],[],
[]}}}}
** Reason for termination ==
** {badarith,[{gs1,handle_call,3,
[{file,"d:/Dropbox/eclipse/WORKSP~1/test1/src/gs1.erl"},
{line,81}]},
{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==== 27-May-2012::10:15:10 ===
** Generic server sup1 terminating
** Last message in was {'EXIT',<0.31.0>,
{{{badarith,
[{gs1,handle_call,3,
[{file,
"d:/Dropbox/eclipse/WORKSP~1/test1/src/gs1.erl"},
{line,81}]},
{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,[gs1,k]}},
[{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,sup1},
one_for_one,
[{child,<0.39.0>,jisuan,
{gs1,start,[]},
permanent,500,worker,
[gs1]}],
undefined,3,10,
[{1338,84910,186000}],
sup1,[]}
** Reason for termination ==
** {{{badarith,[{gs1,handle_call,3,
[{file,"d:/Dropbox/eclipse/WORKSP~1/test1/src/gs1.erl"},
{line,81}]},
{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,[gs1,k]}},
[{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,
[{gs1,handle_call,3,
[{file,

"d:/Dropbox/eclipse/WORKSP~1/test1/src/gs1.erl"},
{line,81}]},
{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,[gs1,k]}}
in function gen_server:call/2 (gen_server.erl, line 180)
6> gs1:g(a).
** exception exit: {noproc,{gen_server,call,[gs1,{g,a}]}}
in function gen_server:call/2 (gen_server.erl, line 180)


附:
gs1.erl

%%% -------------------------------------------------------------------
%%% Author : Administrator
%%% Description :
%%%
%%% Created : 2012-5-24
%%% -------------------------------------------------------------------
-module(gs1).

-behaviour(gen_server).
%% --------------------------------------------------------------------
%% Include files
%% --------------------------------------------------------------------

%% --------------------------------------------------------------------
%% External exports
-export([start/0, s/2, g/1, k/0, stop/0]).

%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).

-record(state, {data}).

%% ====================================================================
%% External functions
%% ====================================================================


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


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

s(Key,Value)->
gen_server:call(?MODULE, {s,Key,Value}).

g(Key)->
gen_server:call(?MODULE, {g,Key}).

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

%% ====================================================================
%% Server functions
%% ====================================================================

%% --------------------------------------------------------------------
%% Function: init/1
%% Description: Initiates the server
%% Returns: {ok, State} |
%% {ok, State, Timeout} |
%% ignore |
%% {stop, Reason}
%% --------------------------------------------------------------------
init([]) ->
io:format("init...~n"),
{ok, #state{data = dict:new()}}.

%% --------------------------------------------------------------------
%% Function: handle_call/3
%% Description: Handling call messages
%% Returns: {reply, Reply, State} |
%% {reply, Reply, State, Timeout} |
%% {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, Reply, State} | (terminate/2 is called)
%% {stop, Reason, State} (terminate/2 is called)
%% --------------------------------------------------------------------
handle_call({s,Key,Value}, From, State) ->
NState = State#state{data=dict:store(Key, Value, State#state.data)},
Reply = ok,
{reply, Reply, NState};


handle_call({g,Key}, From, State) ->
Reply = dict:find(Key, State#state.data),
{reply, Reply, State};

handle_call(k, From, State) ->
0/0,
{reply, 0, State}.



%% --------------------------------------------------------------------
%% Function: handle_cast/2
%% Description: Handling cast messages
%% Returns: {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, State} (terminate/2 is called)
%% --------------------------------------------------------------------
handle_cast(stop, State) ->
{stop, normal, State}.

%% --------------------------------------------------------------------
%% Function: handle_info/2
%% Description: Handling all non call/cast messages
%% Returns: {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, State} (terminate/2 is called)
%% --------------------------------------------------------------------
handle_info(Info, State) ->
{noreply, State}.

%% --------------------------------------------------------------------
%% Function: terminate/2
%% Description: Shutdown the server
%% Returns: any (ignored by gen_server)
%% --------------------------------------------------------------------
terminate(Reason, State) ->
ok.

%% --------------------------------------------------------------------
%% Func: code_change/3
%% Purpose: Convert process state when code is changed
%% Returns: {ok, NewState}
%% --------------------------------------------------------------------
code_change(OldVsn, State, Extra) ->
{ok, State}.

%% --------------------------------------------------------------------
%%% Internal functions
%% --------------------------------------------------------------------



sup1.erl:


%%% -------------------------------------------------------------------
%%% Author : Administrator
%%% Description :
%%%
%%% Created : 2012-5-25
%%% -------------------------------------------------------------------
-module(sup1).

-behaviour(supervisor).
%% --------------------------------------------------------------------
%% Include files
%% --------------------------------------------------------------------

%% --------------------------------------------------------------------
%% External exports
%% --------------------------------------------------------------------
-export([start/0]).

%% --------------------------------------------------------------------
%% Internal exports
%% --------------------------------------------------------------------
-export([
init/1
]).

%% --------------------------------------------------------------------
%% Macros
%% --------------------------------------------------------------------
-define(SERVER, ?MODULE).

%% --------------------------------------------------------------------
%% Records
%% --------------------------------------------------------------------

%% ====================================================================
%% External functions
%% ====================================================================
start()->
supervisor:start_link({local,?MODULE}, ?MODULE, []).


%% ====================================================================
%% Server functions
%% ====================================================================
%% --------------------------------------------------------------------
%% Func: init/1
%% Returns: {ok, {SupFlags, [ChildSpec]}} |
%% ignore |
%% {error, Reason}
%% --------------------------------------------------------------------
init([]) ->
io:format("sup1 init...~n"),
AChild = {jisuan,{gs1,start,[]},
permanent,500,worker,[gs1]},
{ok,{{one_for_one,3,10}, [AChild]}}.

%% ====================================================================
%% Internal functions
%% ====================================================================

filebat Mark

unread,
May 26, 2012, 11:16:56 PM5/26/12
to erlang...@googlegroups.com, ec...@googlegroups.com
handle_call({g,Key}, From, State) ->
Reply = dict:find(Key, State#state.data),
{reply, Reply, State};
有问题.

Hanlde_call预想的是{reply, ok, State}; 而不是{reply, {ok, 1}, State}.
--
Thanks & Regards

Denny Zhang

filebat Mark

unread,
May 26, 2012, 11:18:54 PM5/26/12
to gam...@chenwang.net, erlang...@googlegroups.com
handle_call({g,Key}, From, State) ->
Reply = dict:find(Key, State#state.data),
{reply, Reply, State};
有问题.

Hanlde_call预想的是{reply, ok, State}; 而不是{reply, {ok, 1}, State}.


On Sun, May 27, 2012 at 10:59 AM, gamexg hzly <gam...@chenwang.net> wrote:

孟君乐

unread,
May 26, 2012, 11:44:27 PM5/26/12
to erlang...@googlegroups.com, ec...@googlegroups.com
2012/5/27 filebat Mark <fileba...@gmail.com>:

> handle_call({g,Key}, From, State) ->
> Reply = dict:find(Key, State#state.data),
> {reply, Reply, State};
> 有问题.
>
> Hanlde_call预想的是{reply, ok, State}; 而不是{reply, {ok, 1}, State}.
>

谢谢,不过应该不是这个的问题,修改后问题依旧。
而且手册上写 Hanlde_call 返回值的第二个参数 Reply 作为gen_server:call
函数调用的返回值而提供的,如果必须返回 ok ,那 gen_server 的调用就全部没有返回值了啊。

If the function returns {reply,Reply,NewState},
{reply,Reply,NewState,Timeout} or {reply,Reply,NewState,hibernate},
Reply will be given back to From as the return value of call/2,3 or
included in the return value of multi_call/2,3,4.

filebat Mark

unread,
May 26, 2012, 11:56:04 PM5/26/12
to erlang...@googlegroups.com
哦,刚才试了一下代码,是下面0/0抛异常,然后log有点不直白
,-----------

| handle_call(k, From, State) ->
| 0/0,
| {reply, 0, State}.
`-----------

--

filebat Mark

unread,
May 27, 2012, 12:28:41 AM5/27/12
to erlang...@googlegroups.com, gam...@gmail.com
看样子,是想测试一下supervisor能不能工作。

发现包成一个application的话,gen_server异常的话,supervisor就不会死了。

以前没有这么直接试过,还没太明白原由。

,-----------
| denny@denny-Vostro-1014:/tmp/erlang$ erlc *.erl
| ./gs1.erl:69: Warning: variable 'From' is unused
| ./gs1.erl:74: Warning: variable 'From' is unused
| ./gs1.erl:78: Warning: variable 'From' is unused
| ./gs1.erl:79: Warning: the result of the expression is ignored
(suppress the warning by assigning the expression to the _ variable)
| ./gs1.erl:79: Warning: this expression will fail with a 'badarith' exception
| ./gs1.erl:99: Warning: variable 'Info' is unused
| ./gs1.erl:107: Warning: variable 'Reason' is unused
| ./gs1.erl:107: Warning: variable 'State' is unused
| ./gs1.erl:115: Warning: variable 'Extra' is unused
| ./gs1.erl:115: Warning: variable 'OldVsn' is unused
| denny@denny-Vostro-1014:/tmp/erlang$ erl
| Eshell V5.8.3 (abort with ^G)
| 1> application:start(erlang).
| sup1 init...
| init...
| ok
| 2> sys:get_status(whereis(sup1)).
| {status,<0.36.0>,
| {module,gen_server},
| [[{'$ancestors',[<0.35.0>]},
| {'$initial_call',{supervisor,sup1,1}}],
| running,<0.35.0>,[],
| [{header,"Status for generic server sup1"},
| {data,[{"Status",running},
| {"Parent",<0.35.0>},
| {"Logged events",[]}]},
| {data,[{"State",
| {state,{local,sup1},
| one_for_one,
| [{child,<0.37.0>,gs1,
| {gs1,start_link,[]},
| permanent,500,worker,...}],
| undefined,3,10,[],sup1,[]}}]}]]}
| 3> gs1:k().
|
| =ERROR REPORT==== 27-May-2012::12:26:40 ===
| ** Generic server gs1 terminating
| ** Last message in was k
| ** When Server state == {state,{dict,0,16,16,8,80,48,
| {[],[],[],[],[],[],[],[],[],[],[],[],[],
| [],[],[]},
| {{[],[],[],[],[],[],[],[],[],[],[],[],[],
| [],[],[]}}}}
| ** Reason for termination ==
| ** {badarith,[{gs1,handle_call,3},
| {gen_server,handle_msg,5},
| {proc_lib,init_p_do_apply,3}]}
| init...
| ** exception exit: {{badarith,[{gs1,handle_call,3},
| {gen_server,handle_msg,5},
| {proc_lib,init_p_do_apply,3}]},
| {gen_server,call,[gs1,k]}}
| in function gen_server:call/2
| 4> sys:get_status(whereis(sup1)).
| {status,<0.36.0>,
| {module,gen_server},
| [[{'$ancestors',[<0.35.0>]},
| {'$initial_call',{supervisor,sup1,1}}],
| running,<0.35.0>,[],
| [{header,"Status for generic server sup1"},
| {data,[{"Status",running},
| {"Parent",<0.35.0>},
| {"Logged events",[]}]},
| {data,[{"State",
| {state,{local,sup1},
| one_for_one,
| [{child,<0.40.0>,gs1,
| {gs1,start_link,[]},
| permanent,500,worker,...}],
| undefined,3,10,
| [{1338,92800,92077}],
| sup1,[]}}]}]]}
| 5> gs1:s(a,1).
| ok
`-----------
erlang.tar.gz

孟君乐

unread,
May 27, 2012, 9:13:25 AM5/27/12
to filebat Mark, erlang...@googlegroups.com
包成application的确就正常了,很奇怪的问题...
filebat Mark,谢谢了

2012/5/27 filebat Mark <fileba...@gmail.com>:

filebat Mark

unread,
May 27, 2012, 9:23:13 AM5/27/12
to 孟君乐, erlang...@googlegroups.com
同探索。估计看看otp中supervisor实现代码可以找到答案。

孟君乐 <gam...@gmail.com>编写:

Zheng Zhibin

unread,
May 27, 2012, 10:57:47 AM5/27/12
to erlang...@googlegroups.com, ec...@googlegroups.com
这个问题,很简单。请看下面解释。


Thanks and regards,
==========================
郑智斌(Witeman Zheng)
广州安浩软件科技有限公司
研发总监
公司电邮:wit...@iconventure.com
手机:+86 186 2020 2930
QQ:19653403
==========================

在 2012-5-27,上午10:59, gamexg hzly 写道:

新人学习 erlang ,建了一个简单的 k-v gen_server ,用supervisor 启动它,结果 gen_server
出错重启后,调用 gen_server 提示exception exit:
{noproc,{gen_server,call,[gs1,{g,a}]}}。
看记录显示 gen_server  已经重启了啊,而且没有重启失败的提示。
请问是什么原因造成重启后的 gen_server  调用失败啊?


错误:
Eshell V5.9.1  (abort with ^G)
1> code:add_patha("D:\\Dropbox\\eclipse\\workspace\\test1\\src").
true
2> sup1:start().
这里的start()触发了一个supervisor:start_link,也就是说这个supervisor的进程和shell进程link在一起了!!!

sup1 init...
init...
{ok,<0.34.0>}
3> gs1:s(a,1).
ok
4> gs1:g(a).
{ok,1}
5> gs1:k().   %% 使 gen_server  出错
这里抛出的异常会导致shell进程崩溃,然后shell进程重启了。而之前的shell进程崩溃,会把supervisor也terminate了。
所以这里就会这个情况了

GameXG

unread,
May 27, 2012, 10:15:14 PM5/27/12
to erlang...@googlegroups.com, ec...@googlegroups.com
谢谢,
原来是这个原因啊,真是没有想到。
新启动一个进程就正常了
Eshell V5.9.1
(test@CSZG-85)1> F = fun()-> sup1:start(),receive {exit}->exit end end.
#Fun<erl_eval.20.82930912>
(test@CSZG-85)2> Pid = spawn(F/0).
** exception error: bad argument in an arithmetic expression
in operator '/'/2
called as #Fun<erl_eval.20.82930912> / 0
(test@CSZG-85)3> Pid = spawn(F
).
<0.2449.0>
(test@CSZG-85)4> gs:s(a,1).
** exception error: undefined function gs:s/2
(test@CSZG-85)5> gs1:s(a,1).
ok
(test@CSZG-85)6> gs1
:k().
init...
** exception exit: {{badarith,
[{gs1,handle_call,3,
[{file,

"d:/Dropbox/eclipse/workspace/test1/src/gs1.erl"},
{line,81}]},
{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,[gs1,k]}}
in function gen_server:call/2 (gen_server.erl, line 180)
(test@CSZG-85)7> gs1:g(a).
error
(test@CSZG-85)8> gs1:s(a,1).
ok
(test@CSZG-85)9>

filebat Mark

unread,
May 29, 2012, 11:30:34 AM5/29/12
to erlang...@googlegroups.com, ec...@googlegroups.com
嗯,有道理。

erlang shell会重启,而supervisor已经不会了。这是开始没注意的地方。

,-----------
| denny@denny-Vostro-1014:~/backup/essential/Dropbox/private_data/emacs_stuff/org_data$
erl
| Eshell V5.8.3 (abort with ^G)
| 1> self().
| <0.31.0>
| 2> true=false.
| ** exception error: no match of right hand side value false
| 3> self().
| <0.34.0>
`-----------
Reply all
Reply to author
Forward
0 new messages