如何在Erlang中调试错误?

时间:2011-05-11 06:02:35

标签: erlang

启动我的gen服务器时遇到一个错误,我想知道如何调试它,谢谢!

我运行“example:add_listener(self(),”127.0.0.1“,10999)。”在start_link之后。

错误是:

=ERROR REPORT==== 11-May-2011::13:41:57 ===
** Generic server <0.37.0> terminating 
** Last message in was {'EXIT',<0.35.0>,
                           {{timeout,
                                {gen_server,call,
                                    [<0.35.0>,
                                     {add_listener,"127.0.0.1",10999}]}},
                            [{gen_server,call,2},
                             {erl_eval,do_apply,5},
                             {shell,exprs,6},
                             {shell,eval_exprs,6},
                             {shell,eval_loop,3}]}}
** When Server state == {state,example,
                               {dict,0,16,16,8,80,48,
                                     {[],[],[],[],[],[],[],[],[],[],[],[],[],
                                      [],[],[]},
                                     {{[],[],[],[],[],[],[],[],[],[],[],[],[],
                                       [],[],[]}}},
                               {dict,0,16,16,8,80,48,
                                     {[],[],[],[],[],[],[],[],[],[],[],[],[],
                                      [],[],[]},
                                     {{[],[],[],[],[],[],[],[],[],[],[],[],[],
                                       [],[],[]}}},
                               []}
** Reason for termination == 
** {{timeout,{gen_server,call,[<0.35.0>,{add_listener,"127.0.0.1",10999}]}},
    [{gen_server,call,2},
     {erl_eval,do_apply,5},
     {shell,exprs,6},
     {shell,eval_exprs,6},
     {shell,eval_loop,3}]}
** exception exit: {timeout,{gen_server,call,
                                        [<0.35.0>,{add_listener,"127.0.0.1",10999}]}}
     in function  gen_server:call/2

我的代码是:

-module(test_ess_tcp).

-export([start_link/0,
         add_listener/3,
         remove_listener/3]).

-export([init/2, handle_call/3, handle_cast/2, handle_info/2]).
-export([terminate/2, sock_opts/0, new_connection/4]).

-behavior(ess_tcp).

start_link() ->
    ess_tcp:start_link(?MODULE, []).

add_listener(Pid, IpAddr, Port) ->
    gen_server:call(Pid, {add_listener, IpAddr, Port}).

remove_listener(Pid, IpAddr, Port) ->
    gen_server:call(Pid, {remove_listener, IpAddr, Port}).

init([], State) ->
    %% Example storing callback module specific state
    %% This modifies the server state
    {ok, ess_tcp:store_cb_state([], State)}.

handle_call({add_listener, IpAddr, Port}, _From, State) ->
    %% Example of getting callback module state
    io:format("Not used here, but just an example"),
        [] = ess_tcp:get_cb_state(State),
    case ess_tcp:add_listen_socket({IpAddr, Port}, State) of
        {ok, State1} ->
            {reply, ok, State1};
        Error ->
            {reply, Error, State}
    end;
handle_call({remove_listener, IpAddr, Port}, _From, State) ->
    case ess_tcp:remove_listen_socket({IpAddr, Port}, State) of
        {ok, State1} ->
            {reply, ok, State1};
        Error ->
            {reply, Error, State}
    end;
handle_call(_Msg, _From, State) ->
    {reply, ignored, State}.

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

handle_info({tcp, Sock, Data}, State) ->
    Me = self(),
    P = spawn(fun() -> worker(Me, Sock, Data) end),
    gen_tcp:controlling_process(Sock, P),
    {noreply, State};

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

terminate(_Reason, _State) ->
    ok.

sock_opts() ->
    [binary, {active, once}, {packet, 0}].

new_connection(_IpAddr, _Port, Sock, State) ->
    Me = self(),
    P = spawn(fun() -> worker(Me, Sock) end),
    gen_tcp:controlling_process(Sock, P),
    {ok, State}.

worker(Owner, Sock) ->
    gen_tcp:send(Sock, "Hello\n"),
    inet:setopts(Sock, [{active, once}]),
    gen_tcp:controlling_process(Sock, Owner).

worker(Owner, Sock, Data) ->
    gen_tcp:send(Sock, Data),
    inet:setopts(Sock, [{active, once}]),
    gen_tcp:controlling_process(Sock, Owner).

2 个答案:

答案 0 :(得分:7)

好吧,你的gen_server:调用在调用时会超时。这意味着gen_server要么花费超过默认的3秒超时时间,要么在某个地方被阻止。

使用跟踪调试行为是理想的。例如,如果在运行测试之前在shell中键入此内容:

dbg:tracer(),dbg:p(all,c),dbg:tpl(ess_tcp, x).

您将跟踪ess_tcp中的所有功能,以查看其中发生的情况。有关dbg的更多信息,请参阅http://www.erlang.org/doc/man/dbg.html

答案 1 :(得分:0)

实际上,在erlang中调试的最佳工具是io:format语句。把io:格式放在你怀疑的地方,看看你是否得到了预期的值。 关于上述问题,主要是卡在某处!!