Question

I have a simple_one_for_one supervisor watching over a pool of supervisors, with a child spec similar to

init([]) ->                                                                                                                                                                                
    {ok, {{simple_one_for_one, 60, 5},                                                                                                                                                                      
          [{subsup, {subsup, start_link, []},                                                                                                                                        
            permanent, infinity, supervisor, dynamic}]}}.  

My start_child func looks like this:

start_subsup(Name) ->
    SupName = {via, ?MODULE, Name},
    supervisor:start_child(?MODULE, [SupName]).

Here's the important part: I'm registering via the ?MODULE -- I've properly implemented register_name/2, unregister_name/1, whereis_name/1, and send/2 (backed by an ets table). If necessary, I can post that code also.

My child's start_link func looks like so:

start_link(SupName) ->
    supervisor:start_link(SupName, ?MODULE, []).

Alright, once everything is up and running something like the following will happen:

%% This returns a live pid. cool.    
Pid = sup:whereis_name(name),

%% I can terminate it, and it really dies
ok = supervisor:terminate_child(sup, Pid),
undefined = process_info(Pid),

%% But! it never calls unregister_name!?
Pid = sup:whereis_name(name).

I set all this up so that I can just let the child supervisor die and restart, but it's being blocked by the name not being unregistered.

Thanks in advance!

Était-ce utile?

La solution

It is because you are not implementing the semantics correctly. unregister_name/2 is only called on initialization to break a possible race condition. Otherwise, it is assumed that your ETS module sets a monitor on the registered name so it can automatically remove the name when the process terminates.

Look at gproc for a solution which is already done and more polished than yours.

Autres conseils

You need to trap exit signals for a stopped child to run terminate. Call this in your child process's init:

process_flag(trap_exit, true)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top