[erlang-questions] gen_server restarted by supervisor not working right

Jack Orenstein <>
Wed Oct 17 06:42:36 CEST 2007


I've been going through various pieces of OTP documentation and trying
to put together my own simple code that demonstrates a supervisor
restarting a server.

I see the server starting and then crashing, (the test driver sends a
message that calls exit/1). I see the restart, but then the program
exits, apparently before the test driver's attempt to send a message
to the restarted server.

Here is the test driver, test.erl:

     -module(test).

     -export([main/0]).

     -include_lib("cluster.hrl").

     main() ->
         ?DUMP(cluster_supervisor:start_in_shell_for_testing()),
         ?DUMP(region_server:hello(world)),
         ?DUMP(region_server:crash()),
         ?DUMP(region_server:hello(again)).

The rest of the code appears below, but here is the test output:

     region_server:52 - "{ start_link , RegionNumber }" = {start_link,0}
     region_server:23 - "{ init , ? MODULE , RegionNumber }" = {init,
                                                                    
region_server,
                                                                   0}
     test:8 - "cluster_supervisor : start_in_shell_for_testing ( )" =  
true
     region_server:56 - "{ hello , X }" = {hello,world}
     region_server:30 - "{ hello , X }" = {hello,world}
     test:9 - "region_server : hello ( world )" = {hello,world,0}
     region_server:60 - "crash" = crash
     region_server:33 - "{ crash , RegionNumber }" = {crash,0}
     region_server:43 - "{ terminate , ? MODULE }" =  
{terminate,region_server}

     =ERROR REPORT==== 17-Oct-2007::00:30:41 ===
     ** Generic server region_server terminating
     ** Last message in was {crash}
     ** When Server state == 0
     ** Reason for termination ==
     ** {crash,0}
     region_server:52 - "{ start_link , RegionNumber }" = {start_link,0}
     region_server:23 - "{ init , ? MODULE , RegionNumber }" = {init,
                                                                    
region_server,
                                                                   0}
     {"init terminating in do_boot",{{crash,0},{gen_server,call, 
[region_server,{crash}]}}}

     Crash dump was written to: erl_crash.dump
     init terminating in do_boot ()

The output from region_server:hello(world), before the crash, appears;
but the output from region_server:hello(again), does not.

What am I doing wrong?

Jack Orenstein


Other modules:

Here is cluster_supervisor:

     -module(cluster_supervisor).
     -behavior(supervisor).

     -export([start/0,
              start_in_shell_for_testing/0,
              start_link/1,
              init/1]).

     -include_lib("cluster.hrl").

     start() ->
         spawn(fun() ->
                       supervisor:start_link({local, ?MODULE}, ? 
MODULE, [])
               end).

     start_in_shell_for_testing() ->
         {ok, P} = supervisor:start_link({local, ?MODULE}, ?MODULE, []),
         unlink(P).

     start_link(Args) ->
         supervisor:start_link({local, ?MODULE}, ?MODULE, Args).

     init([]) ->
         {ok, {{one_for_one, 3, 10},
               [{region0,
                 {region_server, start_link, [0]},
                 permanent,
                 10000,
                 worker,
                 [region_server]}
               ]}}.

And here is region_server:

     -module(region_server).
     -behavior(gen_server).

     -include_lib("cluster.hrl").

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

     %% region_server api
     -export([start_link/1,
             hello/1,
             crash/0]).

     %% gen_server api

     init([RegionNumber]) ->
         process_flag(trap_exit, true),
         ?DUMP({init, ?MODULE, RegionNumber}),
         {ok, RegionNumber}.

     handle_call({region}, _From, RegionNumber) ->
         ?DUMP({region, RegionNumber}),
         {reply, {region, RegionNumber}, RegionNumber};
     handle_call({hello, X}, _From, RegionNumber) ->
         ?DUMP({hello, X}),
         {reply, {hello, X, RegionNumber}, RegionNumber};
     handle_call({crash}, _From, RegionNumber) ->
         ?DUMP({crash, RegionNumber}),
         exit({crash, RegionNumber}).

     handle_cast(_Cast, N) ->
         {noreply, N}.

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

     terminate(_Readon, _N) ->
         ?DUMP({terminate, ?MODULE}),
         ok.

     code_change(_, N, _) ->
         {ok, N}.

     %% region_server api

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

     hello(X) ->
         ?DUMP({hello, X}),
         gen_server:call(?MODULE, {hello, X}).

     crash() ->
         ?DUMP(crash),
         gen_server:call(?MODULE, {crash}).

The DUMP macro is defined in cluster.hrl:

     -define(DUMP(X), io:format("~p:~p - ~p = ~p~n", [?MODULE, ? 
LINE, ??X, X])).	



More information about the erlang-questions mailing list