Question

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 ?

Was it helpful?

Solution

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}]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top