|
dear list,
i'm starting three anonymous gen_server from a supervisor. i need every gen_server to know the pid of the other two. 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]. is this the best strategy to achieve this? thank you, r. _______________________________________________ erlang-questions mailing list [hidden email] http://erlang.org/mailman/listinfo/erlang-questions |
|
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 _______________________________________________ erlang-questions mailing list [hidden email] http://erlang.org/mailman/listinfo/erlang-questions |
|
# Vance Shipley 2011-05-18:
> 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>} 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 [hidden email] http://erlang.org/mailman/listinfo/erlang-questions |
fortunately, it is a one_for_all strategy, but good point. Usual ways to handle this: no can do, these have to be anonymous. * Run a name resolution server somewhere and have all the children probably the best would be then to have a gen_event module for this. this is a good idea. * In some cases, you'd start_link those child processes from one i'm adding supervisors because i need it to be as OTP compliant as possible, so I'm actually moving away from this solution. thank you very much vance and jachym for these insights. r. _______________________________________________ erlang-questions mailing list [hidden email] http://erlang.org/mailman/listinfo/erlang-questions |
|
In reply to this post by Roberto Ostinelli
After the supervisor has started a child server won't it then be running completely unsynchronised with the supervisor? In that case how will a server know that all the other servers have been started?
Robert ----- "Vance Shipley" <[hidden email]> 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 > > _______________________________________________ > erlang-questions mailing list > [hidden email] > http://erlang.org/mailman/listinfo/erlang-questions erlang-questions mailing list [hidden email] http://erlang.org/mailman/listinfo/erlang-questions |
|
On Wed, May 18, 2011 at 09:44:59AM +0000, Robert Virding wrote:
} After the supervisor has started a child server won't it then } be running completely unsynchronised with the supervisor? 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. -- -Vance _______________________________________________ erlang-questions mailing list [hidden email] http://erlang.org/mailman/listinfo/erlang-questions |
|
In reply to this post by Jachym Holecek
On Wed, May 18, 2011 at 09:34:22AM +0100, Jachym Holecek wrote:
} 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. 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 _______________________________________________ erlang-questions mailing list [hidden email] http://erlang.org/mailman/listinfo/erlang-questions |
|
In reply to this post by Roberto Ostinelli
>>
>> * 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. > > probably the best would be then to have a gen_event module for this. this is > a good idea. > wouldn't gproc be useful for this? The keys don't have to matter and you can subscribe based on a match/wildcard. _______________________________________________ erlang-questions mailing list [hidden email] http://erlang.org/mailman/listinfo/erlang-questions |
|
On May 18, 2011, at 8:45 AM, Tim Watson wrote:
+1 Although I have to ask why is it really necessary to have children know (dynamically) the pids of all other children.... maybe the system can be re-designed to work around this requirement? Mihai _______________________________________________ erlang-questions mailing list [hidden email] http://erlang.org/mailman/listinfo/erlang-questions |
|
In reply to this post by Vance Shipley
# Vance Shipley 2011-05-18:
> On Wed, May 18, 2011 at 09:34:22AM +0100, Jachym Holecek wrote: > } 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. > > You try it. I already have. Oops, sorry, good point (I mean your reply to Robert). BR, -- Jachym _______________________________________________ erlang-questions mailing list [hidden email] http://erlang.org/mailman/listinfo/erlang-questions |
|
In reply to this post by Tim Watson-5
Also +1 for gproc.
In your supervisor child specs, pass the supervisor's pid as a parameter to each gen_server. Then, have the gen_servers register themselves with gproc as..
{SuperPid, child1} {SuperPid, child2} etc... This way siblings can easily access each other even after child restarts, and you can have many instances of your supervisor/gen_server tree without registration collisions (which I suspect is why you avoided registration to begin with.)
Also, see gproc:await() to synchronize startup with siblings. Dan.
On Wed, May 18, 2011 at 7:45 AM, Tim Watson <[hidden email]> wrote:
-- Daniel Goertzen ----------------- [hidden email] (work) [hidden email] (home) ----------------- 1 204 272 6149 (home/office) 1 204 470 8360 (mobile) ----------------- _______________________________________________ erlang-questions mailing list [hidden email] http://erlang.org/mailman/listinfo/erlang-questions |
| Powered by Nabble | Edit this page |
