gen_server:调用失败,异常退出

时间:2014-06-08 09:15:14

标签: erlang otp gen-server

我在OS X 10.9.2上运行Erlang R16B03-1 (erts-5.10.4)。 Erlang是使用brew安装的。

我正在尝试运行gen_server模块。

-module(logger).
-author("evangelosp").

-behaviour(gen_server).

%% API
-export([start/0, stop/0, log/2]).

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

-define(SERVER, ?MODULE).

%%%===================================================================
%%% API
%%%===================================================================

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

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

log(_Level, _MSG) -> gen_server:call(?MODULE, {add, {_Level, _MSG}}).

%%%===================================================================
%%% gen_server callbacks
%%%===================================================================

init([]) -> {ok, ets:new(?MODULE, [])}.

handle_call(_Request, _From, Table) -> {reply, {ok, ["Mplah!", _Request, _From, Table]}, Table}.

handle_cast(_Request, State) -> {noreply, State}.

handle_info(_Info, State) -> {noreply, State}.

terminate(_Reason, _State) -> ok.

code_change(_OldVsn, State, _Extra) -> {ok, State}.

在我正在运行的erlang shell中:

Eshell V5.10.4  (abort with ^G)
1> c(logger).
{ok,logger}
2> logger:start().
{ok,<0.40.0>}
3> logger:log(info, "Hello World").
** exception exit: {noproc,{gen_server,call,
                                       [logger,{add,{info,"Hello World"}}]}}
     in function  gen_server:call/2 (gen_server.erl, line 180)

我无法摆脱那个例外。我实际上没有通过查找异常消息找到任何有用的资源,但this没有多大帮助。

干杯。

2 个答案:

答案 0 :(得分:2)

在代码start() -> gen_server:start_link({global, ?SERVER}, ?MODULE, [], []).中,您使用{global, ?SERVER},这意味着:

  

如果ServerName = {global,GlobalName},则注册gen_server   使用global:register_name / 2全局作为GlobalName。

因此,当您向服务器发送消息时,您应该写log(_Level, _MSG) -> gen_server:call({global, ?MODULE}, {add, {_Level, _MSG}}).。请参阅erlang doc:

  

呼叫(ServerRef,请求,超时) - &gt;答复   类型:   ServerRef =名称| {Name,Node} | {global,GlobalName} |   ServerRef可以是:

     

名称,如果gen_server是本地注册的,

     

{global,GlobalName},如果gen_server是全局注册的。

答案 1 :(得分:1)

您的服务器未注册,因此只能通过其pid访问。但是接口函数使用隐式宏?MODULE(在编译时由logger替换)来访问它。

您需要更改界面功能,或者在启动功能中注册服务器:

start() ->
  {ok,Pid} = gen_server:start_link({global, ?SERVER}, ?MODULE, [], []),
  register(?MODULE,Pid).

[编辑]感谢Evalon,我在答案中做了更正:o)