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 childs. When I kill the parent, childs are working fine with init as a parent. But if I stop (with SIGSTOP) one of the childs and then kill the parent, childs are killed too. Why this is so?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With