Quantcast

supervisor children's pid

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

supervisor children's pid

Roberto Ostinelli
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
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: supervisor children's pid

Vance Shipley
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

which_sup.erl (362 bytes) Download Attachment
which_server.erl (911 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: supervisor children's pid

Jachym Holecek
# 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
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: supervisor children's pid

Roberto Ostinelli

> }  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.

fortunately, it is a one_for_all strategy, but good point.

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.

no can do, these have to be anonymous.
 
 * 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.
 
 * 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.

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
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: supervisor children's pid

Robert Virding-2
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
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: supervisor children's pid

Vance Shipley
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
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: supervisor children's pid

Vance Shipley
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
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: supervisor children's pid

Tim Watson-5
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
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: supervisor children's pid

Mihai Balea

On May 18, 2011, at 8:45 AM, Tim Watson wrote:

wouldn't gproc be useful for this? The keys don't have to matter and
you can subscribe based on a match/wildcard.

+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
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: supervisor children's pid

Jachym Holecek
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
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: supervisor children's pid

Daniel Goertzen-2
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:
>>
>>  * 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



--
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
Loading...