You can't call the supervisor from the init function of one of it's
own children. You have to return from init/1 before that is possible.
What you can do is to return {ok, State, Timeout} from init/1 with
a Timeout value of 0 and go on with the initialization after the
supervisor has completed starting the children. The attached example
uses a psuedo state to carry on with the initialization:
1> supervisor:start_link(which_sup, []).
Server=1, Siblings=[<0.36.0>,<0.35.0>]
Server=2, Siblings=[<0.36.0>,<0.34.0>]
Server=3, Siblings=[<0.35.0>,<0.34.0>]
{ok,<0.33.0>}
} is this the best strategy to achieve this?
Yes, use supervisor:which_children/1 to learn the siblings.
--
-Vance
Nice trick, but there is no guarantee process' siblings will already be
started after some arbitrary timeout -- try this on a heavily loaded
system... it's just not safe.
> } is this the best strategy to achieve this?
>
> Yes, use supervisor:which_children/1 to learn the siblings.
No, if he's using anything other than one_for_all strategy the Pids
he learns this way may become stale in the future.
Usual ways to handle this:
* Register the processes, if the names need to be dynamic supervisor
can compute them at init/1 and pass to children in arguments.
* Run a name resolution server somewhere and have all the children
subscribe to it. The server will monitor them and may provide
notification facility to announce Pid changes/availability to
anyone interested -- this lets you do safe startup of dependent
processes.
* In some cases, you'd start_link those child processes from one
master server directly (not from supervisor), and use their Pids
directly. Only makes sense if they're very closely bound.
* Probably something else I can't remember right now. :-)
HTH,
-- Jachym
_______________________________________________
erlang-questions mailing list
erlang-q...@erlang.org
http://erlang.org/mailman/listinfo/erlang-questions
> } is this the best strategy to achieve this?No, if he's using anything other than one_for_all strategy the Pids
>
> Yes, use supervisor:which_children/1 to learn the siblings.
he learns this way may become stale in the future.
Usual ways to handle this:
* Register the processes, if the names need to be dynamic supervisor
can compute them at init/1 and pass to children in arguments.
* Run a name resolution server somewhere and have all the children
subscribe to it. The server will monitor them and may provide
notification facility to announce Pid changes/availability to
anyone interested -- this lets you do safe startup of dependent
processes.
* In some cases, you'd start_link those child processes from one
master server directly (not from supervisor), and use their Pids
directly. Only makes sense if they're very closely bound.
Robert
----- "Vance Shipley" <van...@motivity.ca> wrote:
> On Wed, May 18, 2011 at 12:37:02AM +0200, Roberto Ostinelli wrote:
> } currently, i'm calling supervisor:which_children/1 on the init
> function of
> } the gen_servers, and match the Ids to get the Child [Pid].
>
> You can't call the supervisor from the init function of one of it's
> own children. You have to return from init/1 before that is
> possible.
>
> What you can do is to return {ok, State, Timeout} from init/1 with
> a Timeout value of 0 and go on with the initialization after the
> supervisor has completed starting the children. The attached example
> uses a psuedo state to carry on with the initialization:
>
> 1> supervisor:start_link(which_sup, []).
> Server=1, Siblings=[<0.36.0>,<0.35.0>]
> Server=2, Siblings=[<0.36.0>,<0.34.0>]
> Server=3, Siblings=[<0.35.0>,<0.34.0>]
> {ok,<0.33.0>}
>
> } is this the best strategy to achieve this?
>
> Yes, use supervisor:which_children/1 to learn the siblings.
>
>
> --
> -Vance
The supervisor starts each child specification in the order provided.
Sure, the first child started is up and running on his own before the
next ones however in my example the child then calls the supervisor
to learn all the child specifications. The supervisor won't answer
until the last child is started. In my example the supervisor will
have queued requests from the other children when it is finished
starting the last child.
Try adding a delay in the initialization and you'll see the same result:
init([Sup, N]) ->
receive after 4000 -> ok end,
{ok, #state{sup = Sup, state = init, n = N}, 0}.
1> supervisor:start_link(which_sup, []).
Server=1, Siblings=[<0.39.0>,<0.38.0>]
Server=2, Siblings=[<0.39.0>,<0.37.0>]
Server=3, Siblings=[<0.38.0>,<0.37.0>]
{ok,<0.36.0>}
} In that case how will a server know that all the other servers have
} been started?
When their request is handled all initialization is complete.
You try it. I already have.
} > } is this the best strategy to achieve this?
} >
} > Yes, use supervisor:which_children/1 to learn the siblings.
}
} No, if he's using anything other than one_for_all strategy the Pids
} he learns this way may become stale in the future.
My example demonstrates learning the siblings at startup.
Monitoring changes is another question.
--
-Vance
wouldn't gproc be useful for this? The keys don't have to matter and
you can subscribe based on a match/wildcard.
wouldn't gproc be useful for this? The keys don't have to matter and
you can subscribe based on a match/wildcard.
Oops, sorry, good point (I mean your reply to Robert).
BR,
-- Jachym