I have been studying the Linux kernel behaviour for quite some time now, and it’s always been clear to me that:
When a process dies, all its children are given back to the
initprocess (PID 1) until they eventually die.
However, recently, someone with much more experience than me with the kernel told me that:
When a process exits, all its children also die (unless you use
NOHUPin which case they get back toinit).
Now, even though I don’t believe this, I still wrote a simple program to make sure of it. I know I should not rely on time (sleep) for tests since it all depends on process scheduling, yet for this simple case, I think that’s fairly enough.
int main(void){
printf("Father process spawned (%d).n", getpid());
sleep(5);
if(fork() == 0){
printf("Child process spawned (%d => %d).n", getppid(), getpid());
sleep(15);
printf("Child process exiting (%d => %d).n", getppid(), getpid());
exit(0);
}
sleep(5);
printf(stdout, "Father process exiting (%d).n", getpid());
return EXIT_SUCCESS;
}
Here is the program’s output, with the associated ps result every time printf talks:
$ ./test & Father process spawned (435). $ ps -ef | grep test myuser 435 392 tty1 ./test Child process spawned (435 => 436). $ ps -ef | grep test myuser 435 392 tty1 ./test myuser 436 435 tty1 ./test Father process exiting (435). $ ps -ef | grep test myuser 436 1 tty1 ./test Child process exiting (436).
Now, as you can see, this behaves quite as I would have expected it to. The orphan process (436) is given back to init (1) until it dies.
However, is there any UNIX-based system on which this behaviour does not apply by default? Is there any system on which the death of a process immediately triggers the death of all its children?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
When a process exits, all its children also die (unless you use NOHUP in which case they get back to init).
This is wrong. Dead wrong. The person saying that was either mistaken, or confused a particular situation with the the general case.
There are two ways in which the death of a process can indirectly cause the death of its children. They are related to what happens when a terminal is closed. When a terminal disappears (historically because the serial line was cut due to a modem hangup, nowadays usually because the user closed the terminal emulator window), a SIGHUP signal is sent to the controlling process running in that terminal — typically, the initial shell started in that terminal. Shells normally react to this by exiting. Before exiting, shells intended for interactive use send HUP to each job that they started.
Starting a job from a shell with nohup breaks that second source of HUP signals because the job will then ignore the signal and thus not be told to die when the terminal disappears. Other ways to break the propagation of HUP signals from the shell to the jobs include using the shell’s disown builtin if it has one (the job is removed from the shell’s list of jobs), and double forking (the shell launches a child which launches a child of its own and exits immediately; the shell has no knowledge of its grandchild).
Again, the jobs started in the terminal die not because their parent process (the shell) dies, but because their parent process decides to kill them when it is told to kill them. And the initial shell in the terminal dies not because its parent process dies, but because its terminal disappears (which may or may not coincidentally be because the terminal is provided by a terminal emulator which is the shell’s parent process).
Method 2
When a process exits, all its children also die (unless you use NOHUP in which case they get back to init).
This is correct if the process is a session leader. When a session leader dies, a SIGHUP is sent to all members of that session. In practice that means its children and their descendants.
A process makes itself session leader by calling setsid. Shells use this.
Method 3
So what above posters are saying is, the children don’t die, the parent kills them (or sends them a signal on which they terminate).
So you can have what you ask, if you program the Parent to (1) keep a record of all its children, and (2) send a signal to all its children.
This is what the Shell does, and it should be what your parent process does.
It may be necessary to catch the HUP signal in the parent so you still have enough control to kill the children.
Method 4
I am missing one bit in the answers that is slightly related to dying parents: when a process writes on a pipe for which there is no reading process anymore, it gets a SIGPIPE. The standard action for SIGPIPE is termination.
This can indeed cause processes to die. In fact, it is the standard way in which the program yes dies.
If I execute
(yes;echo $? >&2)|head -10
on my system, the answer is
y y y y y y y y y y 141
and 141 is indeed 128+SIGPIPE:
SIGPIPE 13 Term Broken pipe: write to pipe with no
readers
from man 7 signal.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0