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!

Was it helpful?

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.

OTHER TIPS

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