Giter Site home page Giter Site logo

Add child::async_wait about process HOT 10 OPEN

boostorg avatar boostorg commented on June 9, 2024
Add child::async_wait

from process.

Comments (10)

klemens-morgenstern avatar klemens-morgenstern commented on June 9, 2024 1

I decided to not require boost.asio for the usage of booost.process, so the current design doesn't cut it. You can use on_exitfor that, which usesasioandSIGCHLD` under the surface. Does that not cut it for you?

from process.

reddwarf69 avatar reddwarf69 commented on June 9, 2024

I didn't actually notice on_exit was there, sorry. Yes, it's what I need.

from process.

reddwarf69 avatar reddwarf69 commented on June 9, 2024

I actually have some questions...

In https://www.boost.org/doc/libs/1_68_0/doc/html/boost/process/group.html#idp44884880-bb "Wait for the process group to exit" means "wait for any process of the process group to exit" or "wait for all the processes of the process group to exit"? Whatever the case, maybe the docs could be modified to make it extra clear?

I would want to be notified when my child, and every descendant of my child, has exited. This is probably only doable in Linux if cgroups are used, so limiting a bit my request (even if it would be cool to use cgroups to support this): I would want to be notified when my child, and every descendant of my child still in the same process group, has exited. This is not really doable with boost.proccess currently, is it?

Does the behaviour of https://www.boost.org/doc/libs/1_68_0/doc/html/boost/process/on_exit.html depend on whether the child was created with a process group or not? There is a need for an "on_group_exit"?

from process.

klemens-morgenstern avatar klemens-morgenstern commented on June 9, 2024
  1. Yeah, it means all children of the group. Rephrasing might be nice.
  2. I am not sure that's generally possible, since deep nested child processes might be in another group or have a SIGIGN set. You can just get the descriptor of the group through native_handle to use it for extensions - if that cuts it for cgroup.
  3. I am not sure that's feasible, because there's no SIGGRP - how would you implement that?

from process.

reddwarf69 avatar reddwarf69 commented on June 9, 2024

Yeah, at least to start with I would not bother trying to handle children that have changed process group. Those get lost. But I don't think it matters whether SIGCHLD is SIG_IGN in the children themselves, you will still get a signal if your own SIGCHLD is not SIG_IGN. If some child in the hierarchy has SIGCHLD with SIG_IGN either:

  • The grandchildren will clean up by themselves
  • The child will die first, the grandchildren will become your children, and you will waitid() for them.

I guess "on_exit" currently works like this:

  1. Wait for SIGCHLD
  2. Waitid for the children that SIGCHLD has just signalled

"on_group_exit" or "on_exit when the child has been created with a group" could:

  1. Wait for SIGCHLD
  2. waitid() for the children that SIGCHLD has just signalled
  3. (async)Wait for SIGCHLD
  4. waitid() for the process group id using the WNOHANG option
  5. If 4 returns ECHILD it means all the children in the process group have exited, 3 is cancel() and "on_group_exit"/"on_exit" is called

from process.

klemens-morgenstern avatar klemens-morgenstern commented on June 9, 2024

The second doesn't work, because you might lose information, since waitpid might reap a child process from the table while another part of your code waits for it.

from process.

reddwarf69 avatar reddwarf69 commented on June 9, 2024

Not sure I follow you here. But probably what you refer to can be solved by using WNOWAIT, in addition to WNOHANG, in 4?

http://man7.org/linux/man-pages/man2/waitpid.2.html
WNOWAIT Leave the child in a waitable state; a later wait call can be used to again retrieve the child status information.

from process.

klemens-morgenstern avatar klemens-morgenstern commented on June 9, 2024

Ok, so you have process with pid 12 in group 13 and you wait for both asynchronously. If SIGCHLD gets triggered, the waiting for 12 gets it, calls waitpid(12, &status, WNOHANG) to check if it got it. Then it does not forward the signal. Even if it does, the handler for group 13 gets called, checks with waitpid(-13, &status, WNOHANG) but then gets nothing because the information already got handled by the first call. That goes both ways, so we lose information.

from process.

reddwarf69 avatar reddwarf69 commented on June 9, 2024

First, let me say I obviously said something silly with The child will die first, the grandchildren will become your children, and you will waitid() for them. init/"pid 1" becomes the parent of the grandchildren, not you.

The good news is that it's not silly anymore since Linux 3.14, which has PR_SET_CHILD_SUBREAPER. But I don't think you would be interested in something Linux specific, only available since 30 Mar 2014?

But this is what I was proposing:
Supposing I have created a process group, 13, containing processes 12 and 13. Let's suppose PID 13 exits first.

/*
 * FIRST
 *
 * me ->
 *    -> PID 13 ->
 *              -> PID 12
 */

prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0);

asio::signal_set chldSig(ioc, SIGCHLD);
group myGroup;

void do_child_wait() {
	chldSig.async_wait(on_child_wait);
}

void on_child_wait(const error_code& ec, int) {
	// PID 13 has exited
	siginfo_t info;
	waitid(P_PGID, myGroup.native_handle(), &info, WEXITED);
	
	// Add code here to store the returned status if it's the right/main child

        /*
         * NOW
         *
         * me ->
         *    -> PID 12
         */

	int ret = waitid(P_PGID, myGroup.native_handle(), &info, WEXITED | WNOHANG | WNOWAIT); // Checks if there are more children, without blocking and without modifying anything
        if(ret == -1)
		if(errno != ECHILD) {
			on_exit(error)
			return;
		}

		// There are no more children after all
		on_exit(status_code);
		return;
	}

	// There are more children, so let's wait until on_child_wait gets called again by chldSig.async_wait()
	do_child_wait();
}

I have also changed the "3 is cancel()" part from my explanation since I understood chldSig is not going to lose signals between async_wait() calls.

from process.

reddwarf69 avatar reddwarf69 commented on June 9, 2024
1. Yeah, it means all children of the group. Rephrasing might be nice.

FWIW I was now ready to open a different issue about this, since I was testing with boost 1.68. But I see you have fixed it already for 1.69 in eea7375 and it uses a quite similar thing to what I have just mentioned.

But while eea7375 is the best that can be done in a standard way. Using PR_SET_CHILD_SUBREAPER if available would also make boost::process::group::wait() more deterministic. Without PR_SET_CHILD_SUBREAPER, Wait for the process group to exit in boost::process::group::wait() certainly means all children of the group, but not all the processes in the group (some processes can become children of PID 1, not of you) which is what I guess most people will expect to mean.

from process.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.