gen_server 和运行时错误

发布于 2024-10-06 23:47:40 字数 169 浏览 7 评论 0原文

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

I have a run-time error in the init part of a gen_server.
- Init begin by process_flag(trap_exit,true)
- gen_server is part of a supervision tree
I try to print the reason in the terminate module but it seems to exit elsewhere.
- why terminate is not called ?
The application stops with shutdown as reason.
- How and where to catch the run-time error ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

怎樣才叫好 2024-10-13 23:47:40

在这种情况下,通常会调用 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函数,包括spawn问题。

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_sup 来说,foo 的主管:

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

基本开始链接...

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

基本 ChildSpec。让 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}]}

上面我们看到 foo:init/1 发生了崩溃code> 由于异常 blabla

      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}]

The terminate callback is normally called in this situation, namely because you have trapped exits.

The only place where this is not the case is if the crash happens in the init-function. In that case, the responsibility is on the supervisor, who usually terminates itself as a result. Then this error crawls up the supervisor tree until it ends up terminating your whole application.

Usually, the supervisor will log a supervisor report with the context set to start_error. This is your hint that the part of the supervision tree has problems you should handle. You should check for this, because you may have the wrong assumption on where the error occurs.

EDITED FROM HERE

Your problem is that you don't know about SASL at all. Study it. Here is an example of how to use it.

Hoisted code from your example:

First, the bahlonga needed to tell Erlang we have a 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]).

We hack the #state{} record so it can be used with your code

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

Basic start_linkage...

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

Your init function, spawn problem included.

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

Above we have hacked a bit for the sake of simplification...

    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.

Hacks for missing functions....

handle_accept(_) ->
    #state{}.

The rest is just the basics..., so I omit them.

Now for foo_sup the supervisor for foo:

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

Basic start link...

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

Basic ChildSpec. Get the foo child up and running...

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

Boot Erlang with SASL enabled:

 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)

Let us try to spawn the supervisor...

 1> foo_sup:start_link().

And we get this:

=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}]}

Above we see that we have a crash in foo:init/1 due to an exception blabla.

      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:

And now the supervisor gets to report about the problem!

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

The context is exactly as I said it would be...

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

And with the expected reason.

     Offender:   [{pid,undefined},
                  {name,foo},
                  {mfargs,{foo,start_link,[]}},
                  {restart_type,permanent},
                  {shutdown,2000},
                  {child_type,worker}]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文