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?

up vote 66 down vote accepted

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

  • 1
    There's a third way, something with control groups. All I know is that systemd uses it to enforce clean kills. – o11c Oct 2 '14 at 0:55
  • 5
    @JanHudec I think you're confusing nohup with disown. disown is a builtin in some shell that removes a running job from the job table (taking an argument like %1), and the main useful side effect of that is that the shell won't to send a SIGHUP to the subprocess. nohup is an external utility that ignores SIGHUP (and does few other things) then starts the command passed on its command line. – Gilles Oct 2 '14 at 8:07
  • @Gilles: No, I was not, but looking at strace nohup in fact does ignore the signal before it execs the command. – Jan Hudec Oct 2 '14 at 9:40
  • Thank you for your answer! I particularly liked the little bit of historical background concerning modem hang ups. I was beginning to worry I had been misunderstanding the kernel all this time... – John WH Smith Oct 2 '14 at 12:41
  • 3
    Also should be noted that a program exits when it receives SIGHUP because the default signal handler for SIGHUP is to exit. But any program may implement its own SIGHUP handler which may cause it to not exit when the parent shell sends it SIGHUP. – slebetman Oct 3 '14 at 1:47

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.

  • I just ran a test about this, but I couldn't reproduce the behaviour you're describing... I spawned a process, gave it a new session (fork, kill parent process, setsid), and forked another child into this new session. However, when the parent process (new session leader) died, the child received no SIGHUP, and got attached to init until it eventually exited. – John WH Smith Oct 2 '14 at 12:35
  • From setpgid(2) manpage: If a session has a controlling terminal, and the CLOCAL flag for that terminal is not set, and a terminal hangup occurs, then the session leader is sent a SIGHUP. If the session leader exits, then a SIGHUP signal will also be sent to each process in the foreground process group of the controlling terminal. – ninjalj Oct 2 '14 at 20:27
  • 1
    @ninjalj Then I'm guessing this answer is valid if and only if the session leader is also the controlling process of a terminal. A standard session leader, independent from any terminal, won't kill its children. Is it correct? – John WH Smith Oct 3 '14 at 12:04

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.

  • Many a cause can make the parent die. There is no way to prevent survival of the children if the parent is SIGKILLed, for example. – Emil Jeřábek Oct 2 '14 at 17:10

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.

  • 2
    But the process reading from the pipe isn't necessarily (or even usually) its parent. So this is really a very different case from what the question is asking about. – Barmar Oct 8 '14 at 19:02

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.