Process – UNIX Variants Where a Child Process Dies with Its Parent

exitforkinitprocess

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 init process (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 NOHUP in which case they get back to init).

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?

Best Answer

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).

Related Question