src/supervisor2.erl
author Simon MacMullen <simon@rabbitmq.com>
Thu, 18 Sep 2014 16:59:50 +0100
changeset 13971 a3e1a4236fa3
parent 13845 b24c5e148679
permissions -rw-r--r--
Merge bug 26216
     1 %% This file is a copy of supervisor.erl from the R16B Erlang/OTP
     2 %% distribution, with the following modifications:
     3 %%
     4 %% 1) the module name is supervisor2
     5 %%
     6 %% 2) a find_child/2 utility function has been added
     7 %%
     8 %% 3) Added an 'intrinsic' restart type. Like the transient type, this
     9 %%    type means the child should only be restarted if the child exits
    10 %%    abnormally. Unlike the transient type, if the child exits
    11 %%    normally, the supervisor itself also exits normally. If the
    12 %%    child is a supervisor and it exits normally (i.e. with reason of
    13 %%    'shutdown') then the child's parent also exits normally.
    14 %%
    15 %% 4) child specifications can contain, as the restart type, a tuple
    16 %%    {permanent, Delay} | {transient, Delay} | {intrinsic, Delay}
    17 %%    where Delay >= 0 (see point (4) below for intrinsic). The delay,
    18 %%    in seconds, indicates what should happen if a child, upon being
    19 %%    restarted, exceeds the MaxT and MaxR parameters. Thus, if a
    20 %%    child exits, it is restarted as normal. If it exits sufficiently
    21 %%    quickly and often to exceed the boundaries set by the MaxT and
    22 %%    MaxR parameters, and a Delay is specified, then rather than
    23 %%    stopping the supervisor, the supervisor instead continues and
    24 %%    tries to start up the child again, Delay seconds later.
    25 %%
    26 %%    Note that if a child is delay-restarted this will reset the
    27 %%    count of restarts towrds MaxR and MaxT. This matters if MaxT >
    28 %%    Delay, since otherwise we would fail to restart after the delay.
    29 %%
    30 %%    Sometimes, you may wish for a transient or intrinsic child to
    31 %%    exit abnormally so that it gets restarted, but still log
    32 %%    nothing. gen_server will log any exit reason other than
    33 %%    'normal', 'shutdown' or {'shutdown', _}. Thus the exit reason of
    34 %%    {'shutdown', 'restart'} is interpreted to mean you wish the
    35 %%    child to be restarted according to the delay parameters, but
    36 %%    gen_server will not log the error. Thus from gen_server's
    37 %%    perspective it's a normal exit, whilst from supervisor's
    38 %%    perspective, it's an abnormal exit.
    39 %%
    40 %% 5) normal, and {shutdown, _} exit reasons are all treated the same
    41 %%    (i.e. are regarded as normal exits)
    42 %%
    43 %% All modifications are (C) 2010-2013 GoPivotal, Inc.
    44 %%
    45 %% %CopyrightBegin%
    46 %%
    47 %% Copyright Ericsson AB 1996-2012. All Rights Reserved.
    48 %%
    49 %% The contents of this file are subject to the Erlang Public License,
    50 %% Version 1.1, (the "License"); you may not use this file except in
    51 %% compliance with the License. You should have received a copy of the
    52 %% Erlang Public License along with this software. If not, it can be
    53 %% retrieved online at http://www.erlang.org/.
    54 %%
    55 %% Software distributed under the License is distributed on an "AS IS"
    56 %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
    57 %% the License for the specific language governing rights and limitations
    58 %% under the License.
    59 %%
    60 %% %CopyrightEnd%
    61 %%
    62 -module(supervisor2).
    63 
    64 -behaviour(gen_server).
    65 
    66 %% External exports
    67 -export([start_link/2, start_link/3,
    68 	 start_child/2, restart_child/2,
    69 	 delete_child/2, terminate_child/2,
    70 	 which_children/1, count_children/1,
    71 	 find_child/2, check_childspecs/1]).
    72 
    73 %% Internal exports
    74 -export([init/1, handle_call/3, handle_cast/2, handle_info/2,
    75 	 terminate/2, code_change/3]).
    76 -export([try_again_restart/3]).
    77 
    78 %%--------------------------------------------------------------------------
    79 -ifdef(use_specs).
    80 -export_type([child_spec/0, startchild_ret/0, strategy/0, sup_name/0]).
    81 -endif.
    82 %%--------------------------------------------------------------------------
    83 
    84 -ifdef(use_specs).
    85 -type child()    :: 'undefined' | pid().
    86 -type child_id() :: term().
    87 -type mfargs()   :: {M :: module(), F :: atom(), A :: [term()] | undefined}.
    88 -type modules()  :: [module()] | 'dynamic'.
    89 -type delay()    :: non_neg_integer().
    90 -type restart()  :: 'permanent' | 'transient' | 'temporary' | 'intrinsic' | {'permanent', delay()} | {'transient', delay()} | {'intrinsic', delay()}.
    91 -type shutdown() :: 'brutal_kill' | timeout().
    92 -type worker()   :: 'worker' | 'supervisor'.
    93 -type sup_name() :: {'local', Name :: atom()} | {'global', Name :: atom()}.
    94 -type sup_ref()  :: (Name :: atom())
    95                   | {Name :: atom(), Node :: node()}
    96                   | {'global', Name :: atom()}
    97                   | pid().
    98 -type child_spec() :: {Id :: child_id(),
    99                        StartFunc :: mfargs(),
   100                        Restart :: restart(),
   101                        Shutdown :: shutdown(),
   102                        Type :: worker(),
   103                        Modules :: modules()}.
   104 
   105 -type strategy() :: 'one_for_all' | 'one_for_one'
   106                   | 'rest_for_one' | 'simple_one_for_one'.
   107 -endif.
   108 
   109 %%--------------------------------------------------------------------------
   110 
   111 -ifdef(use_specs).
   112 -record(child, {% pid is undefined when child is not running
   113 	        pid = undefined :: child() | {restarting,pid()} | [pid()],
   114 		name            :: child_id(),
   115 		mfargs          :: mfargs(),
   116 		restart_type    :: restart(),
   117 		shutdown        :: shutdown(),
   118 		child_type      :: worker(),
   119 		modules = []    :: modules()}).
   120 -type child_rec() :: #child{}.
   121 -else.
   122 -record(child, {
   123 	        pid = undefined,
   124 		name,
   125 		mfargs,
   126 		restart_type,
   127 		shutdown,
   128 		child_type,
   129 		modules = []}).
   130 -endif.
   131 
   132 -define(DICT, dict).
   133 -define(SETS, sets).
   134 -define(SET, set).
   135 
   136 -ifdef(use_specs).
   137 -record(state, {name,
   138 		strategy               :: strategy(),
   139 		children = []          :: [child_rec()],
   140 		dynamics               :: ?DICT:?DICT() | ?SET:?SET(),
   141 		intensity              :: non_neg_integer(),
   142 		period                 :: pos_integer(),
   143 		restarts = [],
   144 	        module,
   145 	        args}).
   146 -type state() :: #state{}.
   147 -else.
   148 -record(state, {name,
   149 		strategy,
   150 		children = [],
   151 		dynamics,
   152 		intensity,
   153 		period,
   154 		restarts = [],
   155 	        module,
   156 	        args}).
   157 -endif.
   158 
   159 -define(is_simple(State), State#state.strategy =:= simple_one_for_one).
   160 -define(is_permanent(R), ((R =:= permanent) orelse
   161                           (is_tuple(R) andalso
   162                            tuple_size(R) == 2 andalso
   163                            element(1, R) =:= permanent))).
   164 -define(is_explicit_restart(R),
   165         R == {shutdown, restart}).
   166 
   167 -ifdef(use_specs).
   168 -callback init(Args :: term()) ->
   169     {ok, {{RestartStrategy :: strategy(),
   170            MaxR            :: non_neg_integer(),
   171            MaxT            :: non_neg_integer()},
   172            [ChildSpec :: child_spec()]}}
   173     | ignore.
   174 -else.
   175 
   176 -export([behaviour_info/1]).
   177 
   178 behaviour_info(callbacks) ->
   179     [{init,1}];
   180 behaviour_info(_Other) ->
   181     undefined.
   182 
   183 -endif.
   184 -define(restarting(_Pid_), {restarting,_Pid_}).
   185 
   186 %%% ---------------------------------------------------
   187 %%% This is a general process supervisor built upon gen_server.erl.
   188 %%% Servers/processes should/could also be built using gen_server.erl.
   189 %%% SupName = {local, atom()} | {global, atom()}.
   190 %%% ---------------------------------------------------
   191 -ifdef(use_specs).
   192 -type startlink_err() :: {'already_started', pid()}
   193                          | {'shutdown', term()}
   194                          | term().
   195 -type startlink_ret() :: {'ok', pid()} | 'ignore' | {'error', startlink_err()}.
   196 
   197 -spec start_link(Module, Args) -> startlink_ret() when
   198       Module :: module(),
   199       Args :: term().
   200 
   201 -endif.
   202 start_link(Mod, Args) ->
   203     gen_server:start_link(?MODULE, {self, Mod, Args}, []).
   204  
   205 -ifdef(use_specs).
   206 -spec start_link(SupName, Module, Args) -> startlink_ret() when
   207       SupName :: sup_name(),
   208       Module :: module(),
   209       Args :: term().
   210 -endif.
   211 start_link(SupName, Mod, Args) ->
   212     gen_server:start_link(SupName, ?MODULE, {SupName, Mod, Args}, []).
   213  
   214 %%% ---------------------------------------------------
   215 %%% Interface functions.
   216 %%% ---------------------------------------------------
   217 -ifdef(use_specs).
   218 -type startchild_err() :: 'already_present'
   219 			| {'already_started', Child :: child()} | term().
   220 -type startchild_ret() :: {'ok', Child :: child()}
   221                         | {'ok', Child :: child(), Info :: term()}
   222 			| {'error', startchild_err()}.
   223 
   224 -spec start_child(SupRef, ChildSpec) -> startchild_ret() when
   225       SupRef :: sup_ref(),
   226       ChildSpec :: child_spec() | (List :: [term()]).
   227 -endif.
   228 start_child(Supervisor, ChildSpec) ->
   229     call(Supervisor, {start_child, ChildSpec}).
   230 
   231 -ifdef(use_specs).
   232 -spec restart_child(SupRef, Id) -> Result when
   233       SupRef :: sup_ref(),
   234       Id :: child_id(),
   235       Result :: {'ok', Child :: child()}
   236               | {'ok', Child :: child(), Info :: term()}
   237               | {'error', Error},
   238       Error :: 'running' | 'restarting' | 'not_found' | 'simple_one_for_one' |
   239 	       term().
   240 -endif.
   241 restart_child(Supervisor, Name) ->
   242     call(Supervisor, {restart_child, Name}).
   243 
   244 -ifdef(use_specs).
   245 -spec delete_child(SupRef, Id) -> Result when
   246       SupRef :: sup_ref(),
   247       Id :: child_id(),
   248       Result :: 'ok' | {'error', Error},
   249       Error :: 'running' | 'restarting' | 'not_found' | 'simple_one_for_one'.
   250 -endif.
   251 delete_child(Supervisor, Name) ->
   252     call(Supervisor, {delete_child, Name}).
   253 
   254 %%-----------------------------------------------------------------
   255 %% Func: terminate_child/2
   256 %% Returns: ok | {error, Reason}
   257 %%          Note that the child is *always* terminated in some
   258 %%          way (maybe killed).
   259 %%-----------------------------------------------------------------
   260 -ifdef(use_specs).
   261 -spec terminate_child(SupRef, Id) -> Result when
   262       SupRef :: sup_ref(),
   263       Id :: pid() | child_id(),
   264       Result :: 'ok' | {'error', Error},
   265       Error :: 'not_found' | 'simple_one_for_one'.
   266 -endif.
   267 terminate_child(Supervisor, Name) ->
   268     call(Supervisor, {terminate_child, Name}).
   269 
   270 -ifdef(use_specs).
   271 -spec which_children(SupRef) -> [{Id,Child,Type,Modules}] when
   272       SupRef :: sup_ref(),
   273       Id :: child_id() | undefined,
   274       Child :: child() | 'restarting',
   275       Type :: worker(),
   276       Modules :: modules().
   277 -endif.
   278 which_children(Supervisor) ->
   279     call(Supervisor, which_children).
   280 
   281 -ifdef(use_specs).
   282 -spec count_children(SupRef) -> PropListOfCounts when
   283       SupRef :: sup_ref(),
   284       PropListOfCounts :: [Count],
   285       Count :: {specs, ChildSpecCount :: non_neg_integer()}
   286              | {active, ActiveProcessCount :: non_neg_integer()}
   287              | {supervisors, ChildSupervisorCount :: non_neg_integer()}
   288              |{workers, ChildWorkerCount :: non_neg_integer()}.
   289 -endif.
   290 count_children(Supervisor) ->
   291     call(Supervisor, count_children).
   292 
   293 -ifdef(use_specs).
   294 -spec find_child(Supervisor, Name) -> [pid()] when
   295       Supervisor :: sup_ref(),
   296       Name :: child_id().
   297 -endif.
   298 find_child(Supervisor, Name) ->
   299     [Pid || {Name1, Pid, _Type, _Modules} <- which_children(Supervisor),
   300             Name1 =:= Name].
   301 
   302 call(Supervisor, Req) ->
   303     gen_server:call(Supervisor, Req, infinity).
   304 
   305 -ifdef(use_specs).
   306 -spec check_childspecs(ChildSpecs) -> Result when
   307       ChildSpecs :: [child_spec()],
   308       Result :: 'ok' | {'error', Error :: term()}.
   309 -endif.
   310 check_childspecs(ChildSpecs) when is_list(ChildSpecs) ->
   311     case check_startspec(ChildSpecs) of
   312 	{ok, _} -> ok;
   313 	Error -> {error, Error}
   314     end;
   315 check_childspecs(X) -> {error, {badarg, X}}.
   316 
   317 %%%-----------------------------------------------------------------
   318 %%% Called by timer:apply_after from restart/2
   319 -ifdef(use_specs).
   320 -spec try_again_restart(SupRef, Child, Reason) -> ok when
   321       SupRef :: sup_ref(),
   322       Child :: child_id() | pid(),
   323       Reason :: term().
   324 -endif.
   325 try_again_restart(Supervisor, Child, Reason) ->
   326     cast(Supervisor, {try_again_restart, Child, Reason}).
   327 
   328 cast(Supervisor, Req) ->
   329     gen_server:cast(Supervisor, Req).
   330 
   331 %%% ---------------------------------------------------
   332 %%% 
   333 %%% Initialize the supervisor.
   334 %%% 
   335 %%% ---------------------------------------------------
   336 -ifdef(use_specs).
   337 -type init_sup_name() :: sup_name() | 'self'.
   338 
   339 -type stop_rsn() :: {'shutdown', term()}
   340                   | {'bad_return', {module(),'init', term()}}
   341                   | {'bad_start_spec', term()}
   342                   | {'start_spec', term()}
   343                   | {'supervisor_data', term()}.
   344 
   345 -spec init({init_sup_name(), module(), [term()]}) ->
   346         {'ok', state()} | 'ignore' | {'stop', stop_rsn()}.
   347 -endif.
   348 init({SupName, Mod, Args}) ->
   349     process_flag(trap_exit, true),
   350     case Mod:init(Args) of
   351 	{ok, {SupFlags, StartSpec}} ->
   352 	    case init_state(SupName, SupFlags, Mod, Args) of
   353 		{ok, State} when ?is_simple(State) ->
   354 		    init_dynamic(State, StartSpec);
   355 		{ok, State} ->
   356 		    init_children(State, StartSpec);
   357 		Error ->
   358 		    {stop, {supervisor_data, Error}}
   359 	    end;
   360 	ignore ->
   361 	    ignore;
   362 	Error ->
   363 	    {stop, {bad_return, {Mod, init, Error}}}
   364     end.
   365 
   366 init_children(State, StartSpec) ->
   367     SupName = State#state.name,
   368     case check_startspec(StartSpec) of
   369         {ok, Children} ->
   370             case start_children(Children, SupName) of
   371                 {ok, NChildren} ->
   372                     {ok, State#state{children = NChildren}};
   373                 {error, NChildren, Reason} ->
   374                     terminate_children(NChildren, SupName),
   375                     {stop, {shutdown, Reason}}
   376             end;
   377         Error ->
   378             {stop, {start_spec, Error}}
   379     end.
   380 
   381 init_dynamic(State, [StartSpec]) ->
   382     case check_startspec([StartSpec]) of
   383         {ok, Children} ->
   384 	    {ok, State#state{children = Children}};
   385         Error ->
   386             {stop, {start_spec, Error}}
   387     end;
   388 init_dynamic(_State, StartSpec) ->
   389     {stop, {bad_start_spec, StartSpec}}.
   390 
   391 %%-----------------------------------------------------------------
   392 %% Func: start_children/2
   393 %% Args: Children = [child_rec()] in start order
   394 %%       SupName = {local, atom()} | {global, atom()} | {pid(), Mod}
   395 %% Purpose: Start all children.  The new list contains #child's
   396 %%          with pids.
   397 %% Returns: {ok, NChildren} | {error, NChildren, Reason}
   398 %%          NChildren = [child_rec()] in termination order (reversed
   399 %%                        start order)
   400 %%-----------------------------------------------------------------
   401 start_children(Children, SupName) -> start_children(Children, [], SupName).
   402 
   403 start_children([Child|Chs], NChildren, SupName) ->
   404     case do_start_child(SupName, Child) of
   405 	{ok, undefined} when Child#child.restart_type =:= temporary ->
   406 	    start_children(Chs, NChildren, SupName);
   407 	{ok, Pid} ->
   408 	    start_children(Chs, [Child#child{pid = Pid}|NChildren], SupName);
   409 	{ok, Pid, _Extra} ->
   410 	    start_children(Chs, [Child#child{pid = Pid}|NChildren], SupName);
   411 	{error, Reason} ->
   412 	    report_error(start_error, Reason, Child, SupName),
   413 	    {error, lists:reverse(Chs) ++ [Child | NChildren],
   414 	     {failed_to_start_child,Child#child.name,Reason}}
   415     end;
   416 start_children([], NChildren, _SupName) ->
   417     {ok, NChildren}.
   418 
   419 do_start_child(SupName, Child) ->
   420     #child{mfargs = {M, F, Args}} = Child,
   421     case catch apply(M, F, Args) of
   422 	{ok, Pid} when is_pid(Pid) ->
   423 	    NChild = Child#child{pid = Pid},
   424 	    report_progress(NChild, SupName),
   425 	    {ok, Pid};
   426 	{ok, Pid, Extra} when is_pid(Pid) ->
   427 	    NChild = Child#child{pid = Pid},
   428 	    report_progress(NChild, SupName),
   429 	    {ok, Pid, Extra};
   430 	ignore ->
   431 	    {ok, undefined};
   432 	{error, What} -> {error, What};
   433 	What -> {error, What}
   434     end.
   435 
   436 do_start_child_i(M, F, A) ->
   437     case catch apply(M, F, A) of
   438 	{ok, Pid} when is_pid(Pid) ->
   439 	    {ok, Pid};
   440 	{ok, Pid, Extra} when is_pid(Pid) ->
   441 	    {ok, Pid, Extra};
   442 	ignore ->
   443 	    {ok, undefined};
   444 	{error, Error} ->
   445 	    {error, Error};
   446 	What ->
   447 	    {error, What}
   448     end.
   449 
   450 %%% ---------------------------------------------------
   451 %%% 
   452 %%% Callback functions.
   453 %%% 
   454 %%% ---------------------------------------------------
   455 -ifdef(use_specs).
   456 -type call() :: 'which_children' | 'count_children' | {_, _}.	% XXX: refine
   457 -spec handle_call(call(), term(), state()) -> {'reply', term(), state()}.
   458 -endif.
   459 handle_call({start_child, EArgs}, _From, State) when ?is_simple(State) ->
   460     Child = hd(State#state.children),
   461     #child{mfargs = {M, F, A}} = Child,
   462     Args = A ++ EArgs,
   463     case do_start_child_i(M, F, Args) of
   464 	{ok, undefined} when Child#child.restart_type =:= temporary ->
   465 	    {reply, {ok, undefined}, State};
   466 	{ok, Pid} ->
   467 	    NState = save_dynamic_child(Child#child.restart_type, Pid, Args, State),
   468 	    {reply, {ok, Pid}, NState};
   469 	{ok, Pid, Extra} ->
   470 	    NState = save_dynamic_child(Child#child.restart_type, Pid, Args, State),
   471 	    {reply, {ok, Pid, Extra}, NState};
   472 	What ->
   473 	    {reply, What, State}
   474     end;
   475 
   476 %% terminate_child for simple_one_for_one can only be done with pid
   477 handle_call({terminate_child, Name}, _From, State) when not is_pid(Name),
   478 							?is_simple(State) ->
   479     {reply, {error, simple_one_for_one}, State};
   480 
   481 handle_call({terminate_child, Name}, _From, State) ->
   482     case get_child(Name, State, ?is_simple(State)) of
   483 	{value, Child} ->
   484 	    case do_terminate(Child, State#state.name) of
   485 		#child{restart_type=RT} when RT=:=temporary; ?is_simple(State) ->
   486 		    {reply, ok, state_del_child(Child, State)};
   487 		NChild ->
   488 		    {reply, ok, replace_child(NChild, State)}
   489 		end;
   490 	false ->
   491 	    {reply, {error, not_found}, State}
   492     end;
   493 
   494 %%% The requests delete_child and restart_child are invalid for
   495 %%% simple_one_for_one supervisors.
   496 handle_call({_Req, _Data}, _From, State) when ?is_simple(State) ->
   497     {reply, {error, simple_one_for_one}, State};
   498 
   499 handle_call({start_child, ChildSpec}, _From, State) ->
   500     case check_childspec(ChildSpec) of
   501 	{ok, Child} ->
   502 	    {Resp, NState} = handle_start_child(Child, State),
   503 	    {reply, Resp, NState};
   504 	What ->
   505 	    {reply, {error, What}, State}
   506     end;
   507 
   508 handle_call({restart_child, Name}, _From, State) ->
   509     case get_child(Name, State) of
   510 	{value, Child} when Child#child.pid =:= undefined ->
   511 	    case do_start_child(State#state.name, Child) of
   512 		{ok, Pid} ->
   513 		    NState = replace_child(Child#child{pid = Pid}, State),
   514 		    {reply, {ok, Pid}, NState};
   515 		{ok, Pid, Extra} ->
   516 		    NState = replace_child(Child#child{pid = Pid}, State),
   517 		    {reply, {ok, Pid, Extra}, NState};
   518 		Error ->
   519 		    {reply, Error, State}
   520 	    end;
   521 	{value, #child{pid=?restarting(_)}} ->
   522 	    {reply, {error, restarting}, State};
   523 	{value, _} ->
   524 	    {reply, {error, running}, State};
   525 	_ ->
   526 	    {reply, {error, not_found}, State}
   527     end;
   528 
   529 handle_call({delete_child, Name}, _From, State) ->
   530     case get_child(Name, State) of
   531 	{value, Child} when Child#child.pid =:= undefined ->
   532 	    NState = remove_child(Child, State),
   533 	    {reply, ok, NState};
   534 	{value, #child{pid=?restarting(_)}} ->
   535 	    {reply, {error, restarting}, State};
   536 	{value, _} ->
   537 	    {reply, {error, running}, State};
   538 	_ ->
   539 	    {reply, {error, not_found}, State}
   540     end;
   541 
   542 handle_call(which_children, _From, #state{children = [#child{restart_type = temporary,
   543 							     child_type = CT,
   544 							     modules = Mods}]} =
   545 		State) when ?is_simple(State) ->
   546     Reply = lists:map(fun(Pid) -> {undefined, Pid, CT, Mods} end,
   547                       ?SETS:to_list(dynamics_db(temporary, State#state.dynamics))),
   548     {reply, Reply, State};
   549 
   550 handle_call(which_children, _From, #state{children = [#child{restart_type = RType,
   551 							 child_type = CT,
   552 							 modules = Mods}]} =
   553 		State) when ?is_simple(State) ->
   554     Reply = lists:map(fun({?restarting(_),_}) -> {undefined,restarting,CT,Mods};
   555 			 ({Pid, _}) -> {undefined, Pid, CT, Mods} end,
   556 		      ?DICT:to_list(dynamics_db(RType, State#state.dynamics))),
   557     {reply, Reply, State};
   558 
   559 handle_call(which_children, _From, State) ->
   560     Resp =
   561 	lists:map(fun(#child{pid = ?restarting(_), name = Name,
   562 			     child_type = ChildType, modules = Mods}) ->
   563 			  {Name, restarting, ChildType, Mods};
   564 		     (#child{pid = Pid, name = Name,
   565 			     child_type = ChildType, modules = Mods}) ->
   566 			  {Name, Pid, ChildType, Mods}
   567 		  end,
   568 		  State#state.children),
   569     {reply, Resp, State};
   570 
   571 
   572 handle_call(count_children, _From, #state{children = [#child{restart_type = temporary,
   573 							     child_type = CT}]} = State)
   574   when ?is_simple(State) ->
   575     {Active, Count} =
   576 	?SETS:fold(fun(Pid, {Alive, Tot}) ->
   577 			   case is_pid(Pid) andalso is_process_alive(Pid) of
   578 			       true ->{Alive+1, Tot +1};
   579 			       false ->
   580 				   {Alive, Tot + 1}
   581 			   end
   582 		   end, {0, 0}, dynamics_db(temporary, State#state.dynamics)),
   583     Reply = case CT of
   584 		supervisor -> [{specs, 1}, {active, Active},
   585 			       {supervisors, Count}, {workers, 0}];
   586 		worker -> [{specs, 1}, {active, Active},
   587 			   {supervisors, 0}, {workers, Count}]
   588 	    end,
   589     {reply, Reply, State};
   590 
   591 handle_call(count_children, _From,  #state{children = [#child{restart_type = RType,
   592 							      child_type = CT}]} = State)
   593   when ?is_simple(State) ->
   594     {Active, Count} =
   595 	?DICT:fold(fun(Pid, _Val, {Alive, Tot}) ->
   596 			   case is_pid(Pid) andalso is_process_alive(Pid) of
   597 			       true ->
   598 				   {Alive+1, Tot +1};
   599 			       false ->
   600 				   {Alive, Tot + 1}
   601 			   end
   602 		   end, {0, 0}, dynamics_db(RType, State#state.dynamics)),
   603     Reply = case CT of
   604 		supervisor -> [{specs, 1}, {active, Active},
   605 			       {supervisors, Count}, {workers, 0}];
   606 		worker -> [{specs, 1}, {active, Active},
   607 			   {supervisors, 0}, {workers, Count}]
   608 	    end,
   609     {reply, Reply, State};
   610 
   611 handle_call(count_children, _From, State) ->
   612     %% Specs and children are together on the children list...
   613     {Specs, Active, Supers, Workers} =
   614 	lists:foldl(fun(Child, Counts) ->
   615 			   count_child(Child, Counts)
   616 		   end, {0,0,0,0}, State#state.children),
   617 
   618     %% Reformat counts to a property list.
   619     Reply = [{specs, Specs}, {active, Active},
   620 	     {supervisors, Supers}, {workers, Workers}],
   621     {reply, Reply, State}.
   622 
   623 
   624 count_child(#child{pid = Pid, child_type = worker},
   625 	    {Specs, Active, Supers, Workers}) ->
   626     case is_pid(Pid) andalso is_process_alive(Pid) of
   627 	true ->  {Specs+1, Active+1, Supers, Workers+1};
   628 	false -> {Specs+1, Active, Supers, Workers+1}
   629     end;
   630 count_child(#child{pid = Pid, child_type = supervisor},
   631 	    {Specs, Active, Supers, Workers}) ->
   632     case is_pid(Pid) andalso is_process_alive(Pid) of
   633 	true ->  {Specs+1, Active+1, Supers+1, Workers};
   634 	false -> {Specs+1, Active, Supers+1, Workers}
   635     end.
   636 
   637 
   638 %%% If a restart attempt failed, this message is sent via
   639 %%% timer:apply_after(0,...) in order to give gen_server the chance to
   640 %%% check it's inbox before trying again.
   641 -ifdef(use_specs).
   642 -spec handle_cast({try_again_restart, child_id() | pid(), term()}, state()) ->
   643 			 {'noreply', state()} | {stop, shutdown, state()}.
   644 -endif.
   645 handle_cast({try_again_restart,Pid,Reason}, #state{children=[Child]}=State)
   646   when ?is_simple(State) ->
   647     RT = Child#child.restart_type,
   648     RPid = restarting(Pid),
   649     case dynamic_child_args(RPid, dynamics_db(RT, State#state.dynamics)) of
   650 	{ok, Args} ->
   651 	    {M, F, _} = Child#child.mfargs,
   652 	    NChild = Child#child{pid = RPid, mfargs = {M, F, Args}},
   653             try_restart(Child#child.restart_type, Reason, NChild, State);
   654 	error ->
   655             {noreply, State}
   656     end;
   657 
   658 handle_cast({try_again_restart,Name,Reason}, State) ->
   659     %% we still support >= R12-B3 in which lists:keyfind/3 doesn't exist
   660     case lists:keysearch(Name,#child.name,State#state.children) of
   661 	{value, Child = #child{pid=?restarting(_), restart_type=RestartType}} ->
   662             try_restart(RestartType, Reason, Child, State);
   663 	_ ->
   664 	    {noreply,State}
   665     end.
   666 
   667 %%
   668 %% Take care of terminated children.
   669 %%
   670 -ifdef(use_specs).
   671 -spec handle_info(term(), state()) ->
   672         {'noreply', state()} | {'stop', 'shutdown', state()}.
   673 -endif.
   674 handle_info({'EXIT', Pid, Reason}, State) ->
   675     case restart_child(Pid, Reason, State) of
   676 	{ok, State1} ->
   677 	    {noreply, State1};
   678 	{shutdown, State1} ->
   679 	    {stop, shutdown, State1}
   680     end;
   681 
   682 handle_info({delayed_restart, {RestartType, Reason, Child}}, State)
   683   when ?is_simple(State) ->
   684     try_restart(RestartType, Reason, Child, State#state{restarts = []});  %% [1]
   685 handle_info({delayed_restart, {RestartType, Reason, Child}}, State) ->
   686     case get_child(Child#child.name, State) of
   687         {value, Child1} ->
   688             try_restart(RestartType, Reason, Child1,
   689                         State#state{restarts = []}); %% [1]
   690         _What ->
   691             {noreply, State}
   692     end;
   693 %% [1] When we receive a delayed_restart message we want to reset the
   694 %% restarts field since otherwise the MaxT might not have elapsed and
   695 %% we would just delay again and again. Since a common use of the
   696 %% delayed restart feature is for MaxR = 1, MaxT = some huge number
   697 %% (so that we don't end up bouncing around in non-delayed restarts)
   698 %% this is important.
   699 
   700 handle_info(Msg, State) ->
   701     error_logger:error_msg("Supervisor received unexpected message: ~p~n", 
   702 			   [Msg]),
   703     {noreply, State}.
   704 
   705 %%
   706 %% Terminate this server.
   707 %%
   708 -ifdef(use_specs).
   709 -spec terminate(term(), state()) -> 'ok'.
   710 -endif.
   711 terminate(_Reason, #state{children=[Child]} = State) when ?is_simple(State) ->
   712     terminate_dynamic_children(Child, dynamics_db(Child#child.restart_type,
   713                                                   State#state.dynamics),
   714                                State#state.name);
   715 terminate(_Reason, State) ->
   716     terminate_children(State#state.children, State#state.name).
   717 
   718 %%
   719 %% Change code for the supervisor.
   720 %% Call the new call-back module and fetch the new start specification.
   721 %% Combine the new spec. with the old. If the new start spec. is
   722 %% not valid the code change will not succeed.
   723 %% Use the old Args as argument to Module:init/1.
   724 %% NOTE: This requires that the init function of the call-back module
   725 %%       does not have any side effects.
   726 %%
   727 -ifdef(use_specs).
   728 -spec code_change(term(), state(), term()) ->
   729         {'ok', state()} | {'error', term()}.
   730 -endif.
   731 code_change(_, State, _) ->
   732     case (State#state.module):init(State#state.args) of
   733 	{ok, {SupFlags, StartSpec}} ->
   734 	    case catch check_flags(SupFlags) of
   735 		ok ->
   736 		    {Strategy, MaxIntensity, Period} = SupFlags,
   737                     update_childspec(State#state{strategy = Strategy,
   738                                                  intensity = MaxIntensity,
   739                                                  period = Period},
   740                                      StartSpec);
   741 		Error ->
   742 		    {error, Error}
   743 	    end;
   744 	ignore ->
   745 	    {ok, State};
   746 	Error ->
   747 	    Error
   748     end.
   749 
   750 check_flags({Strategy, MaxIntensity, Period}) ->
   751     validStrategy(Strategy),
   752     validIntensity(MaxIntensity),
   753     validPeriod(Period),
   754     ok;
   755 check_flags(What) ->
   756     {bad_flags, What}.
   757 
   758 update_childspec(State, StartSpec) when ?is_simple(State) ->
   759     case check_startspec(StartSpec) of
   760         {ok, [Child]} ->
   761             {ok, State#state{children = [Child]}};
   762         Error ->
   763             {error, Error}
   764     end;
   765 update_childspec(State, StartSpec) ->
   766     case check_startspec(StartSpec) of
   767 	{ok, Children} ->
   768 	    OldC = State#state.children, % In reverse start order !
   769 	    NewC = update_childspec1(OldC, Children, []),
   770 	    {ok, State#state{children = NewC}};
   771         Error ->
   772 	    {error, Error}
   773     end.
   774 
   775 update_childspec1([Child|OldC], Children, KeepOld) ->
   776     case update_chsp(Child, Children) of
   777 	{ok,NewChildren} ->
   778 	    update_childspec1(OldC, NewChildren, KeepOld);
   779 	false ->
   780 	    update_childspec1(OldC, Children, [Child|KeepOld])
   781     end;
   782 update_childspec1([], Children, KeepOld) ->
   783     %% Return them in (kept) reverse start order.
   784     lists:reverse(Children ++ KeepOld).
   785 
   786 update_chsp(OldCh, Children) ->
   787     case lists:map(fun(Ch) when OldCh#child.name =:= Ch#child.name ->
   788 			   Ch#child{pid = OldCh#child.pid};
   789 		      (Ch) ->
   790 			   Ch
   791 		   end,
   792 		   Children) of
   793 	Children ->
   794 	    false;  % OldCh not found in new spec.
   795 	NewC ->
   796 	    {ok, NewC}
   797     end.
   798     
   799 %%% ---------------------------------------------------
   800 %%% Start a new child.
   801 %%% ---------------------------------------------------
   802 
   803 handle_start_child(Child, State) ->
   804     case get_child(Child#child.name, State) of
   805 	false ->
   806 	    case do_start_child(State#state.name, Child) of
   807 		{ok, undefined} when Child#child.restart_type =:= temporary ->
   808 		    {{ok, undefined}, State};
   809 		{ok, Pid} ->
   810 		    {{ok, Pid}, save_child(Child#child{pid = Pid}, State)};
   811 		{ok, Pid, Extra} ->
   812 		    {{ok, Pid, Extra}, save_child(Child#child{pid = Pid}, State)};
   813 		{error, What} ->
   814 		    {{error, {What, Child}}, State}
   815 	    end;
   816 	{value, OldChild} when is_pid(OldChild#child.pid) ->
   817 	    {{error, {already_started, OldChild#child.pid}}, State};
   818 	{value, _OldChild} ->
   819 	    {{error, already_present}, State}
   820     end.
   821 
   822 %%% ---------------------------------------------------
   823 %%% Restart. A process has terminated.
   824 %%% Returns: {ok, state()} | {shutdown, state()}
   825 %%% ---------------------------------------------------
   826 
   827 restart_child(Pid, Reason, #state{children = [Child]} = State) when ?is_simple(State) ->
   828     RestartType = Child#child.restart_type,
   829     case dynamic_child_args(Pid, dynamics_db(RestartType, State#state.dynamics)) of
   830 	{ok, Args} ->
   831 	    {M, F, _} = Child#child.mfargs,
   832 	    NChild = Child#child{pid = Pid, mfargs = {M, F, Args}},
   833 	    do_restart(RestartType, Reason, NChild, State);
   834 	error ->
   835             {ok, State}
   836     end;
   837 
   838 restart_child(Pid, Reason, State) ->
   839     Children = State#state.children,
   840     %% we still support >= R12-B3 in which lists:keyfind/3 doesn't exist
   841     case lists:keysearch(Pid, #child.pid, Children) of
   842 	{value, #child{restart_type = RestartType} = Child} ->
   843 	    do_restart(RestartType, Reason, Child, State);
   844 	false ->
   845 	    {ok, State}
   846     end.
   847 
   848 try_restart(RestartType, Reason, Child, State) ->
   849     case handle_restart(RestartType, Reason, Child, State) of
   850         {ok, NState}       -> {noreply, NState};
   851         {shutdown, State2} -> {stop, shutdown, State2}
   852     end.
   853 
   854 do_restart(RestartType, Reason, Child, State) ->
   855     maybe_report_error(RestartType, Reason, Child, State),
   856     handle_restart(RestartType, Reason, Child, State).
   857 
   858 maybe_report_error(permanent, Reason, Child, State) ->
   859     report_child_termination(Reason, Child, State);
   860 maybe_report_error({permanent, _}, Reason, Child, State) ->
   861     report_child_termination(Reason, Child, State);
   862 maybe_report_error(_Type, Reason, Child, State) ->
   863     case is_abnormal_termination(Reason) of
   864         true  -> report_child_termination(Reason, Child, State);
   865         false -> ok
   866     end.
   867 
   868 report_child_termination(Reason, Child, State) ->
   869     report_error(child_terminated, Reason, Child, State#state.name).
   870 
   871 handle_restart(permanent, _Reason, Child, State) ->
   872     restart(Child, State);
   873 handle_restart(transient, Reason, Child, State) ->
   874     restart_if_explicit_or_abnormal(fun restart/2,
   875                                     fun delete_child_and_continue/2,
   876                                     Reason, Child, State);
   877 handle_restart(intrinsic, Reason, Child, State) ->
   878     restart_if_explicit_or_abnormal(fun restart/2,
   879                                     fun delete_child_and_stop/2,
   880                                     Reason, Child, State);
   881 handle_restart(temporary, _Reason, Child, State) ->
   882     delete_child_and_continue(Child, State);
   883 handle_restart({permanent, _Delay}=Restart, Reason, Child, State) ->
   884     do_restart_delay(Restart, Reason, Child, State);
   885 handle_restart({transient, _Delay}=Restart, Reason, Child, State) ->
   886     restart_if_explicit_or_abnormal(defer_to_restart_delay(Restart, Reason),
   887                                     fun delete_child_and_continue/2,
   888                                     Reason, Child, State);
   889 handle_restart({intrinsic, _Delay}=Restart, Reason, Child, State) ->
   890     restart_if_explicit_or_abnormal(defer_to_restart_delay(Restart, Reason),
   891                                     fun delete_child_and_stop/2,
   892                                     Reason, Child, State).
   893 
   894 restart_if_explicit_or_abnormal(RestartHow, Otherwise, Reason, Child, State) ->
   895     case ?is_explicit_restart(Reason) orelse is_abnormal_termination(Reason) of
   896         true  -> RestartHow(Child, State);
   897         false -> Otherwise(Child, State)
   898     end.
   899 
   900 defer_to_restart_delay(Restart, Reason) ->
   901     fun(Child, State) -> do_restart_delay(Restart, Reason, Child, State) end.
   902 
   903 delete_child_and_continue(Child, State) ->
   904     {ok, state_del_child(Child, State)}.
   905 
   906 delete_child_and_stop(Child, State) ->
   907     {shutdown, state_del_child(Child, State)}.
   908 
   909 is_abnormal_termination(normal)        -> false;
   910 is_abnormal_termination(shutdown)      -> false;
   911 is_abnormal_termination({shutdown, _}) -> false;
   912 is_abnormal_termination(_Other)        -> true.
   913 
   914 do_restart_delay({RestartType, Delay}, Reason, Child, State) ->
   915     case add_restart(State) of
   916         {ok, NState} ->
   917             maybe_restart(NState#state.strategy, Child, NState);
   918         {terminate, _NState} ->
   919             %% we've reached the max restart intensity, but the
   920             %% add_restart will have added to the restarts
   921             %% field. Given we don't want to die here, we need to go
   922             %% back to the old restarts field otherwise we'll never
   923             %% attempt to restart later, which is why we ignore
   924             %% NState for this clause.
   925             _TRef = erlang:send_after(trunc(Delay*1000), self(),
   926                                       {delayed_restart,
   927                                        {{RestartType, Delay}, Reason, Child}}),
   928             {ok, state_del_child(Child, State)}
   929     end.
   930 
   931 restart(Child, State) ->
   932     case add_restart(State) of
   933 	{ok, NState} ->
   934 	    maybe_restart(NState#state.strategy, Child, NState);
   935 	{terminate, NState} ->
   936 	    report_error(shutdown, reached_max_restart_intensity,
   937 			 Child, State#state.name),
   938 	    {shutdown, remove_child(Child, NState)}
   939     end.
   940 
   941 maybe_restart(Strategy, Child, State) ->
   942     case restart(Strategy, Child, State) of
   943         {try_again, Reason, NState2} ->
   944             %% Leaving control back to gen_server before
   945             %% trying again. This way other incoming requsts
   946             %% for the supervisor can be handled - e.g. a
   947             %% shutdown request for the supervisor or the
   948             %% child.
   949             Id = if ?is_simple(State) -> Child#child.pid;
   950                     true -> Child#child.name
   951                  end,
   952             timer:apply_after(0,?MODULE,try_again_restart,[self(),Id,Reason]),
   953             {ok,NState2};
   954         Other ->
   955             Other
   956     end.
   957 
   958 restart(simple_one_for_one, Child, State) ->
   959     #child{pid = OldPid, mfargs = {M, F, A}} = Child,
   960     Dynamics = ?DICT:erase(OldPid, dynamics_db(Child#child.restart_type,
   961 					       State#state.dynamics)),
   962     case do_start_child_i(M, F, A) of
   963 	{ok, Pid} ->
   964 	    NState = State#state{dynamics = ?DICT:store(Pid, A, Dynamics)},
   965 	    {ok, NState};
   966 	{ok, Pid, _Extra} ->
   967 	    NState = State#state{dynamics = ?DICT:store(Pid, A, Dynamics)},
   968 	    {ok, NState};
   969 	{error, Error} ->
   970 	    NState = State#state{dynamics = ?DICT:store(restarting(OldPid), A,
   971 							Dynamics)},
   972 	    report_error(start_error, Error, Child, State#state.name),
   973 	    {try_again, Error, NState}
   974     end;
   975 restart(one_for_one, Child, State) ->
   976     OldPid = Child#child.pid,
   977     case do_start_child(State#state.name, Child) of
   978 	{ok, Pid} ->
   979 	    NState = replace_child(Child#child{pid = Pid}, State),
   980 	    {ok, NState};
   981 	{ok, Pid, _Extra} ->
   982 	    NState = replace_child(Child#child{pid = Pid}, State),
   983 	    {ok, NState};
   984 	{error, Reason} ->
   985 	    NState = replace_child(Child#child{pid = restarting(OldPid)}, State),
   986 	    report_error(start_error, Reason, Child, State#state.name),
   987 	    {try_again, Reason, NState}
   988     end;
   989 restart(rest_for_one, Child, State) ->
   990     {ChAfter, ChBefore} = split_child(Child#child.pid, State#state.children),
   991     ChAfter2 = terminate_children(ChAfter, State#state.name),
   992     case start_children(ChAfter2, State#state.name) of
   993 	{ok, ChAfter3} ->
   994 	    {ok, State#state{children = ChAfter3 ++ ChBefore}};
   995 	{error, ChAfter3, Reason} ->
   996 	    NChild = Child#child{pid=restarting(Child#child.pid)},
   997 	    NState = State#state{children = ChAfter3 ++ ChBefore},
   998 	    {try_again, Reason, replace_child(NChild,NState)}
   999     end;
  1000 restart(one_for_all, Child, State) ->
  1001     Children1 = del_child(Child#child.pid, State#state.children),
  1002     Children2 = terminate_children(Children1, State#state.name),
  1003     case start_children(Children2, State#state.name) of
  1004 	{ok, NChs} ->
  1005 	    {ok, State#state{children = NChs}};
  1006 	{error, NChs, Reason} ->
  1007 	    NChild = Child#child{pid=restarting(Child#child.pid)},
  1008 	    NState = State#state{children = NChs},
  1009 	    {try_again, Reason, replace_child(NChild,NState)}
  1010     end.
  1011 
  1012 restarting(Pid) when is_pid(Pid) -> ?restarting(Pid);
  1013 restarting(RPid) -> RPid.
  1014 
  1015 %%-----------------------------------------------------------------
  1016 %% Func: terminate_children/2
  1017 %% Args: Children = [child_rec()] in termination order
  1018 %%       SupName = {local, atom()} | {global, atom()} | {pid(),Mod}
  1019 %% Returns: NChildren = [child_rec()] in
  1020 %%          startup order (reversed termination order)
  1021 %%-----------------------------------------------------------------
  1022 terminate_children(Children, SupName) ->
  1023     terminate_children(Children, SupName, []).
  1024 
  1025 %% Temporary children should not be restarted and thus should
  1026 %% be skipped when building the list of terminated children, although
  1027 %% we do want them to be shut down as many functions from this module
  1028 %% use this function to just clear everything.
  1029 terminate_children([Child = #child{restart_type=temporary} | Children], SupName, Res) ->
  1030     do_terminate(Child, SupName),
  1031     terminate_children(Children, SupName, Res);
  1032 terminate_children([Child | Children], SupName, Res) ->
  1033     NChild = do_terminate(Child, SupName),
  1034     terminate_children(Children, SupName, [NChild | Res]);
  1035 terminate_children([], _SupName, Res) ->
  1036     Res.
  1037 
  1038 do_terminate(Child, SupName) when is_pid(Child#child.pid) ->
  1039     case shutdown(Child#child.pid, Child#child.shutdown) of
  1040         ok ->
  1041             ok;
  1042         {error, normal} when not ?is_permanent(Child#child.restart_type) ->
  1043             ok;
  1044         {error, OtherReason} ->
  1045             report_error(shutdown_error, OtherReason, Child, SupName)
  1046     end,
  1047     Child#child{pid = undefined};
  1048 do_terminate(Child, _SupName) ->
  1049     Child#child{pid = undefined}.
  1050 
  1051 %%-----------------------------------------------------------------
  1052 %% Shutdowns a child. We must check the EXIT value 
  1053 %% of the child, because it might have died with another reason than
  1054 %% the wanted. In that case we want to report the error. We put a 
  1055 %% monitor on the child an check for the 'DOWN' message instead of 
  1056 %% checking for the 'EXIT' message, because if we check the 'EXIT' 
  1057 %% message a "naughty" child, who does unlink(Sup), could hang the 
  1058 %% supervisor. 
  1059 %% Returns: ok | {error, OtherReason}  (this should be reported)
  1060 %%-----------------------------------------------------------------
  1061 shutdown(Pid, brutal_kill) ->
  1062     case monitor_child(Pid) of
  1063 	ok ->
  1064 	    exit(Pid, kill),
  1065 	    receive
  1066 		{'DOWN', _MRef, process, Pid, killed} ->
  1067 		    ok;
  1068 		{'DOWN', _MRef, process, Pid, OtherReason} ->
  1069 		    {error, OtherReason}
  1070 	    end;
  1071 	{error, Reason} ->      
  1072 	    {error, Reason}
  1073     end;
  1074 shutdown(Pid, Time) ->
  1075     case monitor_child(Pid) of
  1076 	ok ->
  1077 	    exit(Pid, shutdown), %% Try to shutdown gracefully
  1078 	    receive 
  1079 		{'DOWN', _MRef, process, Pid, shutdown} ->
  1080 		    ok;
  1081 		{'DOWN', _MRef, process, Pid, OtherReason} ->
  1082 		    {error, OtherReason}
  1083 	    after Time ->
  1084 		    exit(Pid, kill),  %% Force termination.
  1085 		    receive
  1086 			{'DOWN', _MRef, process, Pid, OtherReason} ->
  1087 			    {error, OtherReason}
  1088 		    end
  1089 	    end;
  1090 	{error, Reason} ->      
  1091 	    {error, Reason}
  1092     end.
  1093 
  1094 %% Help function to shutdown/2 switches from link to monitor approach
  1095 monitor_child(Pid) ->
  1096     
  1097     %% Do the monitor operation first so that if the child dies 
  1098     %% before the monitoring is done causing a 'DOWN'-message with
  1099     %% reason noproc, we will get the real reason in the 'EXIT'-message
  1100     %% unless a naughty child has already done unlink...
  1101     erlang:monitor(process, Pid),
  1102     unlink(Pid),
  1103 
  1104     receive
  1105 	%% If the child dies before the unlik we must empty
  1106 	%% the mail-box of the 'EXIT'-message and the 'DOWN'-message.
  1107 	{'EXIT', Pid, Reason} -> 
  1108 	    receive 
  1109 		{'DOWN', _, process, Pid, _} ->
  1110 		    {error, Reason}
  1111 	    end
  1112     after 0 -> 
  1113 	    %% If a naughty child did unlink and the child dies before
  1114 	    %% monitor the result will be that shutdown/2 receives a 
  1115 	    %% 'DOWN'-message with reason noproc.
  1116 	    %% If the child should die after the unlink there
  1117 	    %% will be a 'DOWN'-message with a correct reason
  1118 	    %% that will be handled in shutdown/2. 
  1119 	    ok   
  1120     end.
  1121 
  1122 
  1123 %%-----------------------------------------------------------------
  1124 %% Func: terminate_dynamic_children/3
  1125 %% Args: Child    = child_rec()
  1126 %%       Dynamics = ?DICT() | ?SET()
  1127 %%       SupName  = {local, atom()} | {global, atom()} | {pid(),Mod}
  1128 %% Returns: ok
  1129 %%
  1130 %%
  1131 %% Shutdown all dynamic children. This happens when the supervisor is
  1132 %% stopped. Because the supervisor can have millions of dynamic children, we
  1133 %% can have an significative overhead here.
  1134 %%-----------------------------------------------------------------
  1135 terminate_dynamic_children(Child, Dynamics, SupName) ->
  1136     {Pids, EStack0} = monitor_dynamic_children(Child, Dynamics),
  1137     Sz = ?SETS:size(Pids),
  1138     EStack = case Child#child.shutdown of
  1139                  brutal_kill ->
  1140                      ?SETS:fold(fun(P, _) -> exit(P, kill) end, ok, Pids),
  1141                      wait_dynamic_children(Child, Pids, Sz, undefined, EStack0);
  1142                  infinity ->
  1143                      ?SETS:fold(fun(P, _) -> exit(P, shutdown) end, ok, Pids),
  1144                      wait_dynamic_children(Child, Pids, Sz, undefined, EStack0);
  1145                  Time ->
  1146                      ?SETS:fold(fun(P, _) -> exit(P, shutdown) end, ok, Pids),
  1147                      TRef = erlang:start_timer(Time, self(), kill),
  1148                      wait_dynamic_children(Child, Pids, Sz, TRef, EStack0)
  1149              end,
  1150     %% Unroll stacked errors and report them
  1151     ?DICT:fold(fun(Reason, Ls, _) ->
  1152                        report_error(shutdown_error, Reason,
  1153                                     Child#child{pid=Ls}, SupName)
  1154                end, ok, EStack).
  1155 
  1156 
  1157 monitor_dynamic_children(#child{restart_type=temporary}, Dynamics) ->
  1158     ?SETS:fold(fun(P, {Pids, EStack}) ->
  1159                        case monitor_child(P) of
  1160                            ok ->
  1161                                {?SETS:add_element(P, Pids), EStack};
  1162                            {error, normal} ->
  1163                                {Pids, EStack};
  1164                            {error, Reason} ->
  1165                                {Pids, ?DICT:append(Reason, P, EStack)}
  1166                        end
  1167                end, {?SETS:new(), ?DICT:new()}, Dynamics);
  1168 monitor_dynamic_children(#child{restart_type=RType}, Dynamics) ->
  1169     ?DICT:fold(fun(P, _, {Pids, EStack}) when is_pid(P) ->
  1170                        case monitor_child(P) of
  1171                            ok ->
  1172                                {?SETS:add_element(P, Pids), EStack};
  1173                            {error, normal} when not ?is_permanent(RType) ->
  1174                                {Pids, EStack};
  1175                            {error, Reason} ->
  1176                                {Pids, ?DICT:append(Reason, P, EStack)}
  1177                        end;
  1178 		  (?restarting(_), _, {Pids, EStack}) ->
  1179 		       {Pids, EStack}
  1180                end, {?SETS:new(), ?DICT:new()}, Dynamics).
  1181 
  1182 wait_dynamic_children(_Child, _Pids, 0, undefined, EStack) ->
  1183     EStack;
  1184 wait_dynamic_children(_Child, _Pids, 0, TRef, EStack) ->
  1185 	%% If the timer has expired before its cancellation, we must empty the
  1186 	%% mail-box of the 'timeout'-message.
  1187     erlang:cancel_timer(TRef),
  1188     receive
  1189         {timeout, TRef, kill} ->
  1190             EStack
  1191     after 0 ->
  1192             EStack
  1193     end;
  1194 wait_dynamic_children(#child{shutdown=brutal_kill} = Child, Pids, Sz,
  1195                       TRef, EStack) ->
  1196     receive
  1197         {'DOWN', _MRef, process, Pid, killed} ->
  1198             wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1,
  1199                                   TRef, EStack);
  1200 
  1201         {'DOWN', _MRef, process, Pid, Reason} ->
  1202             wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1,
  1203                                   TRef, ?DICT:append(Reason, Pid, EStack))
  1204     end;
  1205 wait_dynamic_children(#child{restart_type=RType} = Child, Pids, Sz,
  1206                       TRef, EStack) ->
  1207     receive
  1208         {'DOWN', _MRef, process, Pid, shutdown} ->
  1209             wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1,
  1210                                   TRef, EStack);
  1211 
  1212         {'DOWN', _MRef, process, Pid, normal} when not ?is_permanent(RType) ->
  1213             wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1,
  1214                                   TRef, EStack);
  1215 
  1216         {'DOWN', _MRef, process, Pid, Reason} ->
  1217             wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1,
  1218                                   TRef, ?DICT:append(Reason, Pid, EStack));
  1219 
  1220         {timeout, TRef, kill} ->
  1221             ?SETS:fold(fun(P, _) -> exit(P, kill) end, ok, Pids),
  1222             wait_dynamic_children(Child, Pids, Sz-1, undefined, EStack)
  1223     end.
  1224 
  1225 %%-----------------------------------------------------------------
  1226 %% Child/State manipulating functions.
  1227 %%-----------------------------------------------------------------
  1228 
  1229 %% Note we do not want to save the parameter list for temporary processes as
  1230 %% they will not be restarted, and hence we do not need this information.
  1231 %% Especially for dynamic children to simple_one_for_one supervisors
  1232 %% it could become very costly as it is not uncommon to spawn
  1233 %% very many such processes.
  1234 save_child(#child{restart_type = temporary,
  1235 		  mfargs = {M, F, _}} = Child, #state{children = Children} = State) ->
  1236     State#state{children = [Child#child{mfargs = {M, F, undefined}} |Children]};
  1237 save_child(Child, #state{children = Children} = State) ->
  1238     State#state{children = [Child |Children]}.
  1239 
  1240 save_dynamic_child(temporary, Pid, _, #state{dynamics = Dynamics} = State) ->
  1241     State#state{dynamics = ?SETS:add_element(Pid, dynamics_db(temporary, Dynamics))};
  1242 save_dynamic_child(RestartType, Pid, Args, #state{dynamics = Dynamics} = State) ->
  1243     State#state{dynamics = ?DICT:store(Pid, Args, dynamics_db(RestartType, Dynamics))}.
  1244 
  1245 dynamics_db(temporary, undefined) ->
  1246     ?SETS:new();
  1247 dynamics_db(_, undefined) ->
  1248     ?DICT:new();
  1249 dynamics_db(_,Dynamics) ->
  1250     Dynamics.
  1251 
  1252 dynamic_child_args(Pid, Dynamics) ->
  1253     case ?SETS:is_set(Dynamics) of
  1254         true ->
  1255             {ok, undefined};
  1256         false ->
  1257             ?DICT:find(Pid, Dynamics)
  1258     end.
  1259 
  1260 state_del_child(#child{pid = Pid, restart_type = temporary}, State) when ?is_simple(State) ->
  1261     NDynamics = ?SETS:del_element(Pid, dynamics_db(temporary, State#state.dynamics)),
  1262     State#state{dynamics = NDynamics};
  1263 state_del_child(#child{pid = Pid, restart_type = RType}, State) when ?is_simple(State) ->
  1264     NDynamics = ?DICT:erase(Pid, dynamics_db(RType, State#state.dynamics)),
  1265     State#state{dynamics = NDynamics};
  1266 state_del_child(Child, State) ->
  1267     NChildren = del_child(Child#child.name, State#state.children),
  1268     State#state{children = NChildren}.
  1269 
  1270 del_child(Name, [Ch=#child{pid = ?restarting(_)}|_]=Chs) when Ch#child.name =:= Name ->
  1271     Chs;
  1272 del_child(Name, [Ch|Chs]) when Ch#child.name =:= Name, Ch#child.restart_type =:= temporary ->
  1273     Chs;
  1274 del_child(Name, [Ch|Chs]) when Ch#child.name =:= Name ->
  1275     [Ch#child{pid = undefined} | Chs];
  1276 del_child(Pid, [Ch|Chs]) when Ch#child.pid =:= Pid, Ch#child.restart_type =:= temporary ->
  1277     Chs;
  1278 del_child(Pid, [Ch|Chs]) when Ch#child.pid =:= Pid ->
  1279     [Ch#child{pid = undefined} | Chs];
  1280 del_child(Name, [Ch|Chs]) ->
  1281     [Ch|del_child(Name, Chs)];
  1282 del_child(_, []) ->
  1283     [].
  1284 
  1285 %% Chs = [S4, S3, Ch, S1, S0]
  1286 %% Ret: {[S4, S3, Ch], [S1, S0]}
  1287 split_child(Name, Chs) ->
  1288     split_child(Name, Chs, []).
  1289 
  1290 split_child(Name, [Ch|Chs], After) when Ch#child.name =:= Name ->
  1291     {lists:reverse([Ch#child{pid = undefined} | After]), Chs};
  1292 split_child(Pid, [Ch|Chs], After) when Ch#child.pid =:= Pid ->
  1293     {lists:reverse([Ch#child{pid = undefined} | After]), Chs};
  1294 split_child(Name, [Ch|Chs], After) ->
  1295     split_child(Name, Chs, [Ch | After]);
  1296 split_child(_, [], After) ->
  1297     {lists:reverse(After), []}.
  1298 
  1299 get_child(Name, State) ->
  1300     get_child(Name, State, false).
  1301 get_child(Pid, State, AllowPid) when AllowPid, is_pid(Pid) ->
  1302     get_dynamic_child(Pid, State);
  1303 get_child(Name, State, _) ->
  1304     lists:keysearch(Name, #child.name, State#state.children).
  1305 
  1306 get_dynamic_child(Pid, #state{children=[Child], dynamics=Dynamics}) ->
  1307     DynamicsDb = dynamics_db(Child#child.restart_type, Dynamics),
  1308     case is_dynamic_pid(Pid, DynamicsDb) of
  1309 	true ->
  1310 	    {value, Child#child{pid=Pid}};
  1311 	false ->
  1312 	    RPid = restarting(Pid),
  1313 	    case is_dynamic_pid(RPid, DynamicsDb) of
  1314 		true ->
  1315 		    {value, Child#child{pid=RPid}};
  1316 		false ->
  1317 		    case erlang:is_process_alive(Pid) of
  1318 			true -> false;
  1319 			false -> {value, Child}
  1320 		    end
  1321 	    end
  1322     end.
  1323 
  1324 is_dynamic_pid(Pid, Dynamics) ->
  1325     case ?SETS:is_set(Dynamics) of
  1326 	true ->
  1327 	    ?SETS:is_element(Pid, Dynamics);
  1328 	false ->
  1329 	    ?DICT:is_key(Pid, Dynamics)
  1330     end.
  1331 
  1332 replace_child(Child, State) ->
  1333     Chs = do_replace_child(Child, State#state.children),
  1334     State#state{children = Chs}.
  1335 
  1336 do_replace_child(Child, [Ch|Chs]) when Ch#child.name =:= Child#child.name ->
  1337     [Child | Chs];
  1338 do_replace_child(Child, [Ch|Chs]) ->
  1339     [Ch|do_replace_child(Child, Chs)].
  1340 
  1341 remove_child(Child, State) ->
  1342     Chs = lists:keydelete(Child#child.name, #child.name, State#state.children),
  1343     State#state{children = Chs}.
  1344 
  1345 %%-----------------------------------------------------------------
  1346 %% Func: init_state/4
  1347 %% Args: SupName = {local, atom()} | {global, atom()} | self
  1348 %%       Type = {Strategy, MaxIntensity, Period}
  1349 %%         Strategy = one_for_one | one_for_all | simple_one_for_one |
  1350 %%                    rest_for_one
  1351 %%         MaxIntensity = integer() >= 0
  1352 %%         Period = integer() > 0
  1353 %%       Mod :== atom()
  1354 %%       Args :== term()
  1355 %% Purpose: Check that Type is of correct type (!)
  1356 %% Returns: {ok, state()} | Error
  1357 %%-----------------------------------------------------------------
  1358 init_state(SupName, Type, Mod, Args) ->
  1359     case catch init_state1(SupName, Type, Mod, Args) of
  1360 	{ok, State} ->
  1361 	    {ok, State};
  1362 	Error ->
  1363 	    Error
  1364     end.
  1365 
  1366 init_state1(SupName, {Strategy, MaxIntensity, Period}, Mod, Args) ->
  1367     validStrategy(Strategy),
  1368     validIntensity(MaxIntensity),
  1369     validPeriod(Period),
  1370     {ok, #state{name = supname(SupName,Mod),
  1371 		strategy = Strategy,
  1372 		intensity = MaxIntensity,
  1373 		period = Period,
  1374 		module = Mod,
  1375 		args = Args}};
  1376 init_state1(_SupName, Type, _, _) ->
  1377     {invalid_type, Type}.
  1378 
  1379 validStrategy(simple_one_for_one) -> true;
  1380 validStrategy(one_for_one)        -> true;
  1381 validStrategy(one_for_all)        -> true;
  1382 validStrategy(rest_for_one)       -> true;
  1383 validStrategy(What)               -> throw({invalid_strategy, What}).
  1384 
  1385 validIntensity(Max) when is_integer(Max),
  1386                          Max >=  0 -> true;
  1387 validIntensity(What)               -> throw({invalid_intensity, What}).
  1388 
  1389 validPeriod(Period) when is_integer(Period),
  1390                          Period > 0 -> true;
  1391 validPeriod(What)                   -> throw({invalid_period, What}).
  1392 
  1393 supname(self, Mod) -> {self(), Mod};
  1394 supname(N, _)      -> N.
  1395 
  1396 %%% ------------------------------------------------------
  1397 %%% Check that the children start specification is valid.
  1398 %%% Shall be a six (6) tuple
  1399 %%%    {Name, Func, RestartType, Shutdown, ChildType, Modules}
  1400 %%% where Name is an atom
  1401 %%%       Func is {Mod, Fun, Args} == {atom(), atom(), list()}
  1402 %%%       RestartType is permanent | temporary | transient |
  1403 %%%                      intrinsic | {permanent, Delay} |
  1404 %%%                      {transient, Delay} | {intrinsic, Delay}
  1405 %%                       where Delay >= 0
  1406 %%%       Shutdown = integer() > 0 | infinity | brutal_kill
  1407 %%%       ChildType = supervisor | worker
  1408 %%%       Modules = [atom()] | dynamic
  1409 %%% Returns: {ok, [child_rec()]} | Error
  1410 %%% ------------------------------------------------------
  1411 
  1412 check_startspec(Children) -> check_startspec(Children, []).
  1413 
  1414 check_startspec([ChildSpec|T], Res) ->
  1415     case check_childspec(ChildSpec) of
  1416 	{ok, Child} ->
  1417 	    case lists:keymember(Child#child.name, #child.name, Res) of
  1418 		true -> {duplicate_child_name, Child#child.name};
  1419 		false -> check_startspec(T, [Child | Res])
  1420 	    end;
  1421 	Error -> Error
  1422     end;
  1423 check_startspec([], Res) ->
  1424     {ok, lists:reverse(Res)}.
  1425 
  1426 check_childspec({Name, Func, RestartType, Shutdown, ChildType, Mods}) ->
  1427     catch check_childspec(Name, Func, RestartType, Shutdown, ChildType, Mods);
  1428 check_childspec(X) -> {invalid_child_spec, X}.
  1429 
  1430 check_childspec(Name, Func, RestartType, Shutdown, ChildType, Mods) ->
  1431     validName(Name),
  1432     validFunc(Func),
  1433     validRestartType(RestartType),
  1434     validChildType(ChildType),
  1435     validShutdown(Shutdown, ChildType),
  1436     validMods(Mods),
  1437     {ok, #child{name = Name, mfargs = Func, restart_type = RestartType,
  1438 		shutdown = Shutdown, child_type = ChildType, modules = Mods}}.
  1439 
  1440 validChildType(supervisor) -> true;
  1441 validChildType(worker) -> true;
  1442 validChildType(What) -> throw({invalid_child_type, What}).
  1443 
  1444 validName(_Name) -> true.
  1445 
  1446 validFunc({M, F, A}) when is_atom(M), 
  1447                           is_atom(F), 
  1448                           is_list(A) -> true;
  1449 validFunc(Func)                      -> throw({invalid_mfa, Func}).
  1450 
  1451 validRestartType(permanent)          -> true;
  1452 validRestartType(temporary)          -> true;
  1453 validRestartType(transient)          -> true;
  1454 validRestartType(intrinsic)          -> true;
  1455 validRestartType({permanent, Delay}) -> validDelay(Delay);
  1456 validRestartType({intrinsic, Delay}) -> validDelay(Delay);
  1457 validRestartType({transient, Delay}) -> validDelay(Delay);
  1458 validRestartType(RestartType)        -> throw({invalid_restart_type,
  1459                                                RestartType}).
  1460 
  1461 validDelay(Delay) when is_number(Delay),
  1462                        Delay >= 0 -> true;
  1463 validDelay(What)                  -> throw({invalid_delay, What}).
  1464 
  1465 validShutdown(Shutdown, _) 
  1466   when is_integer(Shutdown), Shutdown > 0 -> true;
  1467 validShutdown(infinity, _)             -> true;
  1468 validShutdown(brutal_kill, _)          -> true;
  1469 validShutdown(Shutdown, _)             -> throw({invalid_shutdown, Shutdown}).
  1470 
  1471 validMods(dynamic) -> true;
  1472 validMods(Mods) when is_list(Mods) ->
  1473     lists:foreach(fun(Mod) ->
  1474 		    if
  1475 			is_atom(Mod) -> ok;
  1476 			true -> throw({invalid_module, Mod})
  1477 		    end
  1478 		  end,
  1479 		  Mods);
  1480 validMods(Mods) -> throw({invalid_modules, Mods}).
  1481 
  1482 %%% ------------------------------------------------------
  1483 %%% Add a new restart and calculate if the max restart
  1484 %%% intensity has been reached (in that case the supervisor
  1485 %%% shall terminate).
  1486 %%% All restarts accured inside the period amount of seconds
  1487 %%% are kept in the #state.restarts list.
  1488 %%% Returns: {ok, State'} | {terminate, State'}
  1489 %%% ------------------------------------------------------
  1490 
  1491 add_restart(State) ->  
  1492     I = State#state.intensity,
  1493     P = State#state.period,
  1494     R = State#state.restarts,
  1495     Now = erlang:now(),
  1496     R1 = add_restart([Now|R], Now, P),
  1497     State1 = State#state{restarts = R1},
  1498     case length(R1) of
  1499 	CurI when CurI  =< I ->
  1500 	    {ok, State1};
  1501 	_ ->
  1502 	    {terminate, State1}
  1503     end.
  1504 
  1505 add_restart([R|Restarts], Now, Period) ->
  1506     case inPeriod(R, Now, Period) of
  1507 	true ->
  1508 	    [R|add_restart(Restarts, Now, Period)];
  1509 	_ ->
  1510 	    []
  1511     end;
  1512 add_restart([], _, _) ->
  1513     [].
  1514 
  1515 inPeriod(Time, Now, Period) ->
  1516     case difference(Time, Now) of
  1517 	T when T > Period ->
  1518 	    false;
  1519 	_ ->
  1520 	    true
  1521     end.
  1522 
  1523 %%
  1524 %% Time = {MegaSecs, Secs, MicroSecs} (NOTE: MicroSecs is ignored)
  1525 %% Calculate the time elapsed in seconds between two timestamps.
  1526 %% If MegaSecs is equal just subtract Secs.
  1527 %% Else calculate the Mega difference and add the Secs difference,
  1528 %% note that Secs difference can be negative, e.g.
  1529 %%      {827, 999999, 676} diff {828, 1, 653753} == > 2 secs.
  1530 %%
  1531 difference({TimeM, TimeS, _}, {CurM, CurS, _}) when CurM > TimeM ->
  1532     ((CurM - TimeM) * 1000000) + (CurS - TimeS);
  1533 difference({_, TimeS, _}, {_, CurS, _}) ->
  1534     CurS - TimeS.
  1535 
  1536 %%% ------------------------------------------------------
  1537 %%% Error and progress reporting.
  1538 %%% ------------------------------------------------------
  1539 
  1540 report_error(Error, Reason, Child, SupName) ->
  1541     ErrorMsg = [{supervisor, SupName},
  1542 		{errorContext, Error},
  1543 		{reason, Reason},
  1544 		{offender, extract_child(Child)}],
  1545     error_logger:error_report(supervisor_report, ErrorMsg).
  1546 
  1547 
  1548 extract_child(Child) when is_list(Child#child.pid) ->
  1549     [{nb_children, length(Child#child.pid)},
  1550      {name, Child#child.name},
  1551      {mfargs, Child#child.mfargs},
  1552      {restart_type, Child#child.restart_type},
  1553      {shutdown, Child#child.shutdown},
  1554      {child_type, Child#child.child_type}];
  1555 extract_child(Child) ->
  1556     [{pid, Child#child.pid},
  1557      {name, Child#child.name},
  1558      {mfargs, Child#child.mfargs},
  1559      {restart_type, Child#child.restart_type},
  1560      {shutdown, Child#child.shutdown},
  1561      {child_type, Child#child.child_type}].
  1562 
  1563 report_progress(Child, SupName) ->
  1564     Progress = [{supervisor, SupName},
  1565 		{started, extract_child(Child)}],
  1566     error_logger:info_report(progress, Progress).