How to find Pids of the children of a supervisor

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

How to find Pids of the children of a supervisor

Joe Armstrong-2
I was asked the following in a direct mail to me:

"Given two worker processes in a supervision tree, A and B, if A wants
to message B, how should it obtain the pid of B ?"

Pretty good question.

I think the answer is to use supervisor:which_children/1 and to name
the supervisor and all the children.

Is the the best way? - does anybody have an example?

Cheers

/Joe
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: How to find Pids of the children of a supervisor

Vance Shipley
On Thu, Dec 7, 2017 at 6:03 PM, Joe Armstrong <[hidden email]> wrote:

> I was asked the following in a direct mail to me:
>
> "Given two worker processes in a supervision tree, A and B, if A wants
> to message B, how should it obtain the pid of B ?"
>
> Pretty good question.
>
> I think the answer is to use supervisor:which_children/1 and to name
> the supervisor and all the children.
>
> Is the the best way? - does anybody have an example?

Sure, I don't bother to name the supervisor though, pass the pid() down:

Here's an example of a gen_server which locates it's sibling
simple_one_for_one supervisors after initializing:
https://github.com/sigscale/ocs/blob/8aafd48fd876b7434517b512d79d2c12559889bb/src/ocs_radius_auth_port_server.erl#L157



--
     -Vance
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: How to find Pids of the children of a supervisor

Pierre Fenoll-2
supervisor:which_children/1
> Is the the best way? - does anybody have an example?

That and using erlang:process_info(Pid, links) are the only ways.

The supervisor module lacks a child(SupRef, Name) function that would now be able to fetch children by Name
with a complexity better than O(n) now that the module can use maps.
I started writing a PR for that but then got confused by the code that can either use sets or maps: I couldn't understand which backend would be used when...

My use case is to not register names for child processes (using erlang:register via {local,Name}).



Cheers,
-- 
Pierre Fenoll


On 7 December 2017 at 14:26, Vance Shipley <[hidden email]> wrote:
On Thu, Dec 7, 2017 at 6:03 PM, Joe Armstrong <[hidden email]> wrote:
> I was asked the following in a direct mail to me:
>
> "Given two worker processes in a supervision tree, A and B, if A wants
> to message B, how should it obtain the pid of B ?"
>
> Pretty good question.
>
> I think the answer is to use supervisor:which_children/1 and to name
> the supervisor and all the children.
>
> Is the the best way? - does anybody have an example?

Sure, I don't bother to name the supervisor though, pass the pid() down:

Here's an example of a gen_server which locates it's sibling
simple_one_for_one supervisors after initializing:
https://github.com/sigscale/ocs/blob/8aafd48fd876b7434517b512d79d2c12559889bb/src/ocs_radius_auth_port_server.erl#L157



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

Re: How to find Pids of the children of a supervisor

Jesper Louis Andersen-2
I tend to use one out of the following solutions:

* If the processes are truly "singletons" then I tend to register them in the registry (locally or globally) and then look them up there by name.
* Sometimes, A spawns B in the same supervisor. In that case, you obtain B's pid() as part of the spawn and can store it. Of course, if B goes away, so does A need to so you need to handle crashing in the right way here.
* Use a registry: either a process, or just pick up the excellent `gproc` system by Ulf Wiger if needed and use that.
* In a distributed system, I think there is enough interesting stuff going on right now that I'd resurvey the area and pick a registry with the guarantees I need in the system.
* Some of my old code used `supervisor:which_children()` but the more experience I have, the more often I tend to use a registry application for these kinds of things. Keeping a manager process, or an ETS table (gproc) is usually an easier way to obtain other pids().
* Do not underestimate having *another* process who passes the information around. Solve stuff with an indirection!


On Thu, Dec 7, 2017 at 3:34 PM Pierre Fenoll <[hidden email]> wrote:
supervisor:which_children/1
> Is the the best way? - does anybody have an example?

That and using erlang:process_info(Pid, links) are the only ways.

The supervisor module lacks a child(SupRef, Name) function that would now be able to fetch children by Name
with a complexity better than O(n) now that the module can use maps.
I started writing a PR for that but then got confused by the code that can either use sets or maps: I couldn't understand which backend would be used when...

My use case is to not register names for child processes (using erlang:register via {local,Name}).



Cheers,
-- 
Pierre Fenoll

On 7 December 2017 at 14:26, Vance Shipley <[hidden email]> wrote:
On Thu, Dec 7, 2017 at 6:03 PM, Joe Armstrong <[hidden email]> wrote:
> I was asked the following in a direct mail to me:
>
> "Given two worker processes in a supervision tree, A and B, if A wants
> to message B, how should it obtain the pid of B ?"
>
> Pretty good question.
>
> I think the answer is to use supervisor:which_children/1 and to name
> the supervisor and all the children.
>
> Is the the best way? - does anybody have an example?

Sure, I don't bother to name the supervisor though, pass the pid() down:

Here's an example of a gen_server which locates it's sibling
simple_one_for_one supervisors after initializing:
https://github.com/sigscale/ocs/blob/8aafd48fd876b7434517b512d79d2c12559889bb/src/ocs_radius_auth_port_server.erl#L157



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

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: How to find Pids of the children of a supervisor

Vance Shipley
On Thu, Dec 7, 2017 at 9:17 PM, Jesper Louis Andersen
<[hidden email]> wrote:
> * Some of my old code used `supervisor:which_children()` but the more
> experience I have, the more often I tend to use a registry application for
> these kinds of things. Keeping a manager process, or an ETS table (gproc) is
> usually an easier way to obtain other pids().

I like to stick to functional programming as much as possible, if a
function needs some data pass it in as an argument.

--
     -Vance
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: How to find Pids of the children of a supervisor

zxq9-2
In reply to this post by Joe Armstrong-2
On 2017年12月07日 木曜日 13:33:36 Joe Armstrong wrote:

> I was asked the following in a direct mail to me:
>
> "Given two worker processes in a supervision tree, A and B, if A wants
> to message B, how should it obtain the pid of B ?"
>
> Pretty good question.
>
> I think the answer is to use supervisor:which_children/1 and to name
> the supervisor and all the children.
>
> Is the the best way? - does anybody have an example?

I tend to use a (semi) standard template of:

service_sup
    service_manager
    worker_sup
        workers

I wrote about it in a (poorly structured and unrevised) post here:
https://zxq9.com/archives/1311

I'm going to take a stab at this frequently asked question here in email first, and maybe refine it into something worthy of a post on this specific subject later.

The worker_sup may or may not even be started, things might be linked/monitored together in arbitrary ways, etc, but the basic pattern seems to always wind up forming one way or another regardless how the project is designed to start with (before assumptions have been subjected to reality).

SOMETHING must be a named, universal interface to the service (from the perspective of other services in the system, assuming there is more than one), and very often the nature of the service itself is one where workers form arbitrary relationships amongst themselves.

In the case of a broadcast-type service amongst processes (a chat service or update notification system, for example) the connection handlers are one service and the channels themselves are components of another: no peer lookup is necessary except when it comes time to find the pid of a channel to send a subscription request to -- then you send the lookup request to the named service manager of the chat service.

In the case that the same chat or channelized service also supports private messaging, it would be natural for the connection handler's service manager to keep a registry of connected and active pids (which you would do anyway if you want to be able to inspect the system's active state in more interesting ways than merely looking up a list of child pids from the supervisor). So how to resolve a chat username to a pid? Any chat_client worker asks the chat_client_man -- and finds out maybe not just the pid, but also how long he's been logged on, whether he's logged on, IP, or whatever other `finger` type data might be tracked by the system.

The bottom line is that this little pyramid of processes seems to nearly always be needed to define a discrete service, and every time you need to find a sibling's pid the reason for finding it dictates that you have some custom tracking and query code surrounding the lookup -- and that means the natural place for a lookup is in the service manager in nearly every case.

-Craig

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions