Stopping a process with its supervision subtree

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Stopping a process with its supervision subtree

Karolis Petrauskas-2
Hello,

In my application I have a processes (lets say P_X), that are started
by starting a dedicated supervisor (S_X), which starts the process P_X
and several related processes as its children. The S_X supervisors are
started under the one_for_one supervisor (say MainSup). The
supervision tree schematically looks as the following for two P_X
started, when X = 1..2.

    MainSup
      * S_1
          * P_1
          * Other_1
      * S_2
          * P_2
          * Other_2

I need to stop the entire supervisor S_X when the process P_X is done
with its job.

Is it OK to call supervisor:stop_child(MainSup, X) from P_X process? I
experimented with that and it works. Just I'm now not sure, if this is
a correct way for doing that. The following is an excerpt from the
P_X:

    handle_info(deadline, State = #state{x = X}) ->
        ok = supervisor:terminate_child(MainSup, X),
        io:format("Stopped ~p~n", [X]),
        {stop, normal, State};

The last two lines are not executed, as the supervisor:terminate_child
is synchronous and returns only after the P_X is terminated.

Another option, as I understand, would be to start a process above the
MainSup and monitor all P_X processes and then stop the corresponding
supervisors S_X when the DOWN messages are received. Although I would
like to avoid creating such processes as well as to implement own
supervisor.

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

Re: Stopping a process with its supervision subtree

dmkolesnikov
Hello,

This is a good question! I’d like to get other's opinion on the subject as well.
I would go with following pattern:

* S_X is {one_for_all, 0, 1} and all its child are permanent.
* The process P_2 just {stop, normal, State} when the job is done.

I do not like to “leak” a knowledge of supervisor to child processes. I’ll try to avoid usage of supervisor:terminate_child(…). On another hand, this pattern has disadvantage. You’ll see a “supervisor” S_X crash in the log when P_2 stops due to “permanent” property.    

The usage of simple_one_to_one supervisor seems to be right for this type of use-cases but it misses concept of related processes.

What do you think?

Best Regards,
Dmitry



> On Sep 14, 2016, at 11:42 AM, Karolis Petrauskas <[hidden email]> wrote:
>
> Hello,
>
> In my application I have a processes (lets say P_X), that are started
> by starting a dedicated supervisor (S_X), which starts the process P_X
> and several related processes as its children. The S_X supervisors are
> started under the one_for_one supervisor (say MainSup). The
> supervision tree schematically looks as the following for two P_X
> started, when X = 1..2.
>
>    MainSup
>      * S_1
>          * P_1
>          * Other_1
>      * S_2
>          * P_2
>          * Other_2
>
> I need to stop the entire supervisor S_X when the process P_X is done
> with its job.
>
> Is it OK to call supervisor:stop_child(MainSup, X) from P_X process? I
> experimented with that and it works. Just I'm now not sure, if this is
> a correct way for doing that. The following is an excerpt from the
> P_X:
>
>    handle_info(deadline, State = #state{x = X}) ->
>        ok = supervisor:terminate_child(MainSup, X),
>        io:format("Stopped ~p~n", [X]),
>        {stop, normal, State};
>
> The last two lines are not executed, as the supervisor:terminate_child
> is synchronous and returns only after the P_X is terminated.
>
> Another option, as I understand, would be to start a process above the
> MainSup and monitor all P_X processes and then stop the corresponding
> supervisors S_X when the DOWN messages are received. Although I would
> like to avoid creating such processes as well as to implement own
> supervisor.
>
> Karolis
> _______________________________________________
> 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: Stopping a process with its supervision subtree

Karolis Petrauskas-2
Hello,

On Wed, Sep 14, 2016 at 8:20 PM, Dmitry Kolesnikov
<[hidden email]> wrote:

> Hello,
>
> This is a good question! I’d like to get other's opinion on the subject as well.
> I would go with following pattern:
>
> * S_X is {one_for_all, 0, 1} and all its child are permanent.
> * The process P_2 just {stop, normal, State} when the job is done.
>
> I do not like to “leak” a knowledge of supervisor to child processes. I’ll try to avoid usage of supervisor:terminate_child(…). On another hand, this pattern has disadvantage. You’ll see a “supervisor” S_X crash in the log when P_2 stops due to “permanent” property.
>
> The usage of simple_one_to_one supervisor seems to be right for this type of use-cases but it misses concept of related processes.
>
> What do you think?
>

Your note on the knowledge leak to the child process is right.
Sometimes I make child processes to know, how to start themselves
within its supervisor, e.g.

    -module(p).
    start_sup(X) -> p_sup:start_child(X).
    start_link(X) -> gen_server:start_link(...).

In this case, the process knows the supervisor anyway, so addition of
the call for stopping the process is not making things worse (at least
with knowledge leaking). Although I am not sure, if the process module
should have knowledge on the supervision tree, or it is better to
leave that knowledge to the caller/client process.

Your approach is interesting. I haven't considered it. I'm not sure,
if it would allow to differentiate between crashes of P_X (exits with
reason /= normal) and the normal termination. The same is for
differentiation between the main process (P_X) and its helper
processes). The false crash reports would make log analysis more
complicated: it would be not enough to find [error] to consider it
error. Admins wouldn't be happy about that.

>
> Best Regards,
> Dmitry
>
>

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

Re: Stopping a process with its supervision subtree

Jachym Holecek
In reply to this post by dmkolesnikov
Hi,

# Dmitry Kolesnikov 2016-09-14:

> This is a good question! I?d like to get other's opinion on the subject as well.
> I would go with following pattern:
>
> * S_X is {one_for_all, 0, 1} and all its child are permanent.
> * The process P_2 just {stop, normal, State} when the job is done.
>
> I do not like to ?leak? a knowledge of supervisor to child processes. I?ll try to
> avoid usage of supervisor:terminate_child(?). On another hand, this pattern has
> disadvantage. You?ll see a ?supervisor? S_X crash in the log when P_2 stops due to
> ?permanent? property.

Not knowing the full use case at hand I'll say that supervisors are generally used
to manage the long-lived part of process hierarchy. It is a perfectly reasonable
and common pattern to have a process manage its own children without supervisors,
using just links and/or trap_exit and/or monitors. So when your "management" pro-
cess terminates its auxiliary processes are shut down as well. That's why these
primitives are built into the language after all.

Feel free to elaborate more precisely on what you're trying to do and why, in case
the above doesn't seem helpful.

> The usage of simple_one_to_one supervisor seems to be right for this type of
> use-cases but it misses concept of related processes.

I think simple_one_to_one supervisors are something of a historical mistake, their
behaviour differes noticeably from the normal supervision strategies (enough so to
come across as an inconsistency) and the functionality they offer is ridiculously
easy to implement oneself in a way that exactly matches the use case at hand, not
complicating things with unnecessary abstractions.

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

Re: Stopping a process with its supervision subtree

Ingela Andin
Hi!

2016-09-19 11:14 GMT+02:00 Jachym Holecek <[hidden email]>:
Hi,

# Dmitry Kolesnikov 2016-09-14:
> This is a good question! I?d like to get other's opinion on the subject as well.
> I would go with following pattern:
>
> * S_X is {one_for_all, 0, 1} and all its child are permanent.
> * The process P_2 just {stop, normal, State} when the job is done.
>
> I do not like to ?leak? a knowledge of supervisor to child processes. I?ll try to
> avoid usage of supervisor:terminate_child(?). On another hand, this pattern has
> disadvantage. You?ll see a ?supervisor? S_X crash in the log when P_2 stops due to
> ?permanent? property.

Not knowing the full use case at hand I'll say that supervisors are generally used
to manage the long-lived part of process hierarchy. It is a perfectly reasonable
and common pattern to have a process manage its own children without supervisors,
using just links and/or trap_exit and/or monitors. So when your "management" pro-
cess terminates its auxiliary processes are shut down as well. That's why these
primitives are built into the language after all.


Supervisors is not only useful for restarts, they are also useful for clean process management. Used to gracefully stop applications making sure all application processes indeed are closed.
Also if you do soft upgrade "by the book" the supervisors will be used to suspend processes before performing the upgrade instructions.

I use monitors for processes that I need to interact with that are not part of my application. Links are the primitives used to implement supervisors.

 
Feel free to elaborate more precisely on what you're trying to do and why, in case
the above doesn't seem helpful.

> The usage of simple_one_to_one supervisor seems to be right for this type of
> use-cases but it misses concept of related processes.

I think simple_one_to_one supervisors are something of a historical mistake, their
behaviour differes noticeably from the normal supervision strategies (enough so to
come across as an inconsistency) and the functionality they offer is ridiculously
easy to implement oneself in a way that exactly matches the use case at hand, not
complicating things with unnecessary abstractions.



I do not think they are a mistake, I think they where a missed use case and then added add hock, maybe without enough design considerations. Just because it is easy, it does not
necessarily mean you should reinvent the wheel.
 
Regards Ingela Erlang/OTP team - Ericsson AB

 
BR,
        -- Jachym
_______________________________________________
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