Issue
My test code is
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main() {
int c = fork();
if (c == 0) while(1);
c = fork();
if (c == 0) while(1);
c = fork();
if (c == 0) while(1);
c = fork();
if (c == 0) while(1);
while(1);
}
So I have one parent and 4 children. When I kill the parent, the children are working fine with init as a parent. But if I stop (with SIGSTOP) one of the children and then kill the parent, the children are killed too. Why this is so?
Solution
Apparently if a process in the process group is stopped, all processes are signalled with SIGHUP and then SIGCONT when the process group leader is terminated. The default handler for SIGHUP terminates the process. It is expected behaviour, as documented in e.g.
http://www.win.tue.nl/~aeb/linux/lk/lk-10.html
From the above link:
If termination of a process causes a process group to become orphaned, and some member is stopped, then all are sent first SIGHUP and then SIGCONT.
The idea is that perhaps the parent of the process group leader is a job control shell. (In the same session but a different process group.) As long as this parent is alive, it can handle the stopping and starting of members in the process group. When it dies, there may be nobody to continue stopped processes. Therefore, these stopped processes are sent SIGHUP, so that they die unless they catch or ignore it, and then SIGCONT to continue them.
EDIT:
BTW, strace is a wonderful tool for getting to the bottom of stuff like this. If you attach strace to one of the child processes you will see that SIGHUP is delivered only if one of then is stopped when the parent (i.e. the process group leader) dies.
You need to change the handler for SIGHUP using e.g. sigaction(2) if you want the children processes to survive.
Answered By - thkala Answer Checked By - Dawn Plyler (WPSolving Volunteer)