[ related information ]
* prctl
* See linux kerne for details ("kernel/exit.c : find_new_reaper())

------ commit(kernel/git/torvalds/linux.git) -----
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=ebec18a6d3aa1e7d84aab16225e87fd25170ec2b

author	  Lennart Poettering <lennart@poettering.net>    2012-03-23 22:01:54 (GMT)
committer Linus Torvalds <torvalds@linux-foundation.org> 2012-03-23 23:58:32 (GMT)
commit	  ebec18a6d3aa1e7d84aab16225e87fd25170ec2b (patch)




=====================================================================
[ test code ]
-------------

$ cat b.sh
function echosleep2 {
    sleep 10
    echo 'sleep2 end'
}


function echosleep {
    echosleep2&
    sleep 5
    echo 'sleep end'
}

echo "hello: $BASHPID $$"
echosleep&
sleep 2
echo end
=====================================================================




=====================================================================
[common]
--------

  PID  PPID  PGID   SID CMD
 3241  2573  3241  3241 init --user
 ...
 4392  3241  3374  3374 gnome-terminal
 ...
 9882  4392  9882  9882 bash
 ...
=====================================================================



=====================================================================
[ < 2 seconds ]
---------------

  PID  PPID  PGID   SID CMD
33513  9882 33513  9882 bash            # ./b.sh (*a)
33514 33513 33513  9882 bash            # ./b.sh:echosleep() (*b)
33515 33513 33513  9882 sleep 2
33516 33514 33513  9882 bash            # ./b.sh:echosleep():echosleep2() (*c)
33517 33514 33513  9882 sleep 5
33518 33516 33513  9882 sleep 10
33519 15742 33519 15742 ps -e -o pid,ppid,pgid,sid,cmd
-------------

(*a): Bash terminal executed 'b.sh' as new process group leader.
      All child/grandchild processes are executed in the same process group.
=====================================================================




=====================================================================
[ < 5 seconds ]
---------------

  PID  PPID  PGID   SID CMD
33514  3241 33513  9882 bash            # ./b.sh:echosleep() (*b)
33516 33514 33513  9882 bash            # ./b.sh:echosleep():echosleep2() (*c)
33517 33514 33513  9882 sleep 5
33518 33516 33513  9882 sleep 10
33520 15742 33520 15742 ps -e -o pid,ppid,pgid,sid,cmd
-------------

(*b): Process group leader(*a) is disappeared.
      And there is no threads in this process.
      (If there is other threads in this process, it will become new reaper)
      So, it is re-parented to orphan-reaper("init --user").
=====================================================================



=====================================================================
[ < 10 seconds ]
----------------

  PID  PPID  PGID   SID CMD
33516  3241 33513  9882 bash            # ./b.sh:echosleep():echosleep2() (*c)
33518 33516 33513  9882 sleep 10
33522 15742 33522 15742 ps -e -o pid,ppid,pgid,sid,cmd
-------------

(*c): Same with above(*b).
=====================================================================



=====================================================================
[ > 10 seconds ]
----------------

  PID  PPID  PGID   SID CMD
33524 15742 33524 15742 ps -e -o pid,ppid,pgid,sid,cmd
-------------

=====================================================================


Sample code to get every SIGCHLD from descendents.
---------------------------------------------------


#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/prctl.h>
#include <errno.h>

void handle_signal(int signal) {
        pid_t pid;
        printf("Handler SIGCHLD: %d\n", signal);
        if (0 > (pid = wait(NULL))) {
		printf("Wait fails: errno: %s", strerror(errno));
	} else {
		printf("Wait done: %d\n", pid);
	}
}

int main() {
        struct sigaction sa;
	pid_t pid;

        // Print pid, so that we can send signals from other shells
        printf("My pid is: %d\n", getpid());

        // Setup the sighub handler
        sa.sa_handler = &handle_signal;

        // Intercept SIGHUP and SIGINT
        if (sigaction(SIGCHLD, &sa, NULL) == -1) {
                perror("Error: cannot handle SIGCHLD"); // Should not happen
        }

        if (0 > prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0)) {
                perror("Error: prctl");
        }

	pid = fork();
	if (pid) {
		int secs = 10;
		// parent
		printf("\nSleeping for 10 second\n");
		while (secs > 0)
			secs = sleep(10);
		printf("Parent DONE\n");
	} else {
		// child
		if (0 > execlp("bash", "bash", "b.sh", NULL)) {
			printf("execl fails: %s\n", strerror(errno));
		}
	}
}




+ Recent posts