Supervisor shutdown

Ulf Wiger ulf.wiger@REDACTED
Tue Nov 25 12:56:50 CET 2003


On Tue, 25 Nov 2003 13:09:46 +0200, HEINRICH VENTER 
<HEINRICH.VENTER@REDACTED> wrote:

> The gen_sever spawns some worker processes that need to be termianted.  
> These processes might not terminate immediately when the stop message is 
> sent to them. (I have discovered a falw in the curent design but will 
> post to a separate thread about this)  The gen_server can not terminate 
> before all its workers have terminated in an orderly fasion, BUT since 
> the stop function executes in a handle_call and the workers notify the 
> gen_server of their termination through a different handle_call.

You can use monitors to make sure that your server doesn't
hang while waiting for a child process that may have died trying
to do the orderly shutdown:

terminate_children(Children) ->
    MRefs = lists:foldl(
               fun(Child, Acc) ->
                  MRef = erlang:monitor(process, Child),
                  Child ! {self(), shutdown},
                  [MRef | Acc]
               end, [], Children),
    collect_mrefs(MRefs).

collect_mrefs(MRrefs) ->
    timer:sleep(100),
    collect_mrefs(MRefs, []).

collect_mrefs(Rest, Left) ->
    receive
       {'DOWN',MRef,process,_,_} ->
          collect_mrefs(Rest, Left)
    after 0 ->
       collect_mrefs(MRefs, [MRef|Left])
    end;
collect_mrefs([], [_|_] = Left) ->
    collect_mrefs(Left);
collect_mrefs([], []) ->
    done.

If you want to be really paranoid, you could start
a timer using erlang:send_after() before entering the
collect_.. loop. This way (if you keep the child pids
as well), you can do your own version of brutal_kill
if the children never terminate on their own accord.


It would then be good if the child doesn't call the parent
synchronously in order to notify it of their own death
(in general, it's a bad idea to have gen_server:call()
in both directions between two processes.)


> This brings me to the {noreply, State} mentioned in another thread.
> How do I know the PID where to send the response at the later time when 
> I am ready to quit?  The process dictionary perhaps?

You can keep a 'pending' list in your State variable.

> Then use the function that notifies the gen_server of the process 
> termination to check if all the processes are down and then reply with 
> the {stop, normal, ok, State} message instead of {reply, State}
> Does this make sense?

As mentioned above, it's dangerous to only rely on the children
telling the parent that they are about to die. Monitors are quite
handy for this sort of thing.

/Uffe
-- 
Ulf Wiger, Senior System Architect
EAB/UPD/S



More information about the erlang-questions mailing list