3
votes

I define simple_one_for_one worker spec for one supervisor named band_supervisor, and the child spec id is jam_musician:

  init([]) ->
    {ok, {{simple_one_for_one, 3, 60},
    [{jam_musician,
    {musicians, start_link, []},
    temporary, 1000, worker, [musicians]}
    ]}};

musicians module is:

-module(musicians).
-behaviour(gen_server).

-export([start_link/2, stop/1]).
-export([init/1, handle_call/3, handle_cast/2,
handle_info/2, code_change/3, terminate/2]).

-record(state, {name="", role, skill=good}).
-define(DELAY, 750).

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

stop(Role) -> gen_server:call(Role, stop).

and I can create many workers by:

3> supervisor:start_child(band_supervisor, [drum, good]).
Musician Arnold Ramon, playing the drum entered the room
{ok,<0.696.0>}
3> supervisor:start_child(band_supervisor, [guitar, good]).
Musician Wanda Perlstein, playing the guitar entered the room
{ok,<0.698.0>}

I notice that all workers have the same Child spec Id: jam_musician

You know other type workers must has the unique child id, Right ?

2
Could you post your code for the musicians module, please? It looks like you are registering the child processes with the same name.Isac
Yes, your code please for the supervisor module as well. Something is wrong as you cannot get an already_started from a simple_one_for_one supervisor.rvirding
@Isac have updated , the child spec id can be duplicated ?why

2 Answers

6
votes

Most likely you wrote the start_link function of the child process (I assume it is a gen_server) as:

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

This not only calls the init/1 function but also registers the process using the atom Name.

Therefore any new child started in a second moment will try to register inside the erlang node using a name already taken by the first child.

In order to avoid such name clashing you should use something like:

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

So that no child will have a registered name and you will have no clashing.

If you really need to register every child an option may consist in the use of gproc.

5
votes

The child specification identifier will be the same for simple_one_for_one supervisors since there is only one child type and many child instances (workers) of this type.

From the supervisor behaviour docs:

Notice that when the restart strategy is simple_one_for_one, the list of child specifications must be a list with one child specification only. (The child specification identifier is ignored.) No child process is then started during the initialization phase, but all children are assumed to be started dynamically using start_child/2.