erlang - gen_server 和运行时错误

标签 erlang erlang-otp

我在 gen_server 的 init 部分遇到运行时错误。 - 初始化由 process_flag(trap_exit,true) 开始 - gen_server 是监督树的一部分 我尝试在终止模块中打印原因,但它似乎在其他地方退出。 - 为什么不调用终止? 应用程序因关闭而停止。 - 如何以及在哪里捕获运行时错误?

最佳答案

在这种情况下通常会调用 terminate 回调,即因为您已陷入退出状态。

唯一不是这种情况的地方是崩溃发生在 init 函数中。在这种情况下,责任就落在主管身上,而主管通常会因此而解职。然后这个错误会爬上supervisor树,直到最终终止你的整个应用程序。

通常,主管会记录主管报告,并将上下文设置为 start_error。这是你的暗示,监督树的部分有问题,你应该处理。您应该检查这一点,因为您可能对错误发生的位置有错误的假设。

从此处编辑

你的问题是你根本不了解SASL。研究一下。这是如何使用它的示例。

从您的示例中提升代码:

首先,bahlonga 需要告诉 Erlang 我们有一个 gen_server。

-module(foo).
-behaviour(gen_server).
-export([start_link/0]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
     terminate/2, code_change/3]).

我们破解了 #state{} 记录,以便将其与您的代码一起使用

-record(state, { name, port, socket_listen }).

基本的start_linkage...

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

你的初始化函数,包括生成问题。

init([]) ->
    Port = 3252,
    Name = "foo",

为了简化,我们在上面做了一些修改...

    process_flag(trap_exit, true),
    erlang:error(blabla),
    Opts = [binary, {reuseaddr, true},
        {backlog,5}, {packet, 0}, {active, false}, {nodelay, true}],
    case gen_tcp:listen(Port,Opts) of
    {ok,Socket_Listen} ->
        logger:fmsg("--> [~s,init] Socket_Listen crée = ~p",
            [Name,Socket_Listen]),
        {ok,handle_accept(#state{socket_listen=Socket_Listen})};
    {error, Reason} ->
        logger:fmsg("--> [~s,init] Erreur, Raison =~p",
            [Name,Reason]), {stop, Reason}
    end.

修复缺失功能......

handle_accept(_) ->
    #state{}.

剩下的只是基础知识...,所以我省略了。

现在,foo_supfoo的主管:

-module(foo_sup).
-behaviour(supervisor).
-export([start_link/0]).
-export([init/1]).
-define(SERVER, ?MODULE).

基本开始链接...

start_link() ->
    supervisor:start_link({local, ?SERVER}, ?MODULE, []).

基本子规范。让 foo 子进程启动并运行...

init([]) ->
    FooCh = {foo, {foo, start_link, []},
         permanent, 2000, worker, [foo]},
    {ok, {{one_for_all,0,1}, [FooCh]}}.

在启用 SASL 的情况下启动 Erlang:

 jlouis@illithid:~$ erl -boot start_sasl
 Erlang R14B02 (erts-5.8.3) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]

 =PROGRESS REPORT==== 9-Dec-2010::01:01:51 ===
 [..]
 Eshell V5.8.3  (abort with ^G)

让我们尝试生成主管...

 1> foo_sup:start_link().

我们得到这个:

=CRASH REPORT==== 9-Dec-2010::01:05:48 ===
  crasher:
    initial call: foo:init/1
    pid: <0.58.0>
    registered_name: []
    exception exit: {blabla,[{foo,init,1},
                             {gen_server,init_it,6},
                             {proc_lib,init_p_do_apply,3}]}

在上面我们看到,由于 blabla 异常,我们在 foo:init/1 中发生了崩溃。

      in function  gen_server:init_it/6
    ancestors: [foo_sup,<0.45.0>]
    messages: []
    links: [<0.57.0>]
    dictionary: []
    trap_exit: true
    status: running
    heap_size: 233
    stack_size: 24
    reductions: 108
  neighbours:

现在主管可以报告问题!

=SUPERVISOR REPORT==== 9-Dec-2010::01:05:48 ===
     Supervisor: {local,foo_sup}
     Context:    start_error

上下文完全正如我所说......

     Reason:     {blabla,[{foo,init,1},
                          {gen_server,init_it,6},
                          {proc_lib,init_p_do_apply,3}]}

并且有预期的原因。

     Offender:   [{pid,undefined},
                  {name,foo},
                  {mfargs,{foo,start_link,[]}},
                  {restart_type,permanent},
                  {shutdown,2000},
                  {child_type,worker}]

关于erlang - gen_server 和运行时错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4388281/

相关文章:

sockets - erlang:到controlling_process(),或者不到controlling_process()

erlang - 我应该为此使用什么 OTP 行为?

sockets - gen_tcp :recv/2 returns error, einval

erlang - Erlang:如何将Elvis样式检查正确插入rebar3项目?

recursion - Erlang-递归删除

erlang - 为什么在这个函数中使用了 "when"?

Erlang gen_server vs 无状态模块

scala - 如何在非对称系统中将对象发送到远程 akka actor

erlang - 主管启动后启动动态 simple_one_for_one worker

erlang - 如何使用 Cowboy 通过 websocket 异步发送数据?