Search code examples
unixfork

In double fork, why can't grandchild exit before child exit?


Double Fork

In my understanding, double fork is used when a process wants to fork a background process, but 1. it does not want to wait for it AND 2. the background process should be reaped after it exits.

As a result, double fork only requires parent process waits for child process, which should exit immediately after forking grandchild process, and grandchild process is in charge of the real task as a background process.

Context

According to this excerpt from APUE, the grandchild sleeps 2 seconds to make sure its parent (the child) exits before it exits, so that it will be an orphan and init will take care of it and reap it when it exits.

#include "apue.h"
#include <sys/wait.h>

int
main(void)
{
    pid_t   pid;

    if ((pid = fork()) < 0) {
        err_sys("fork error");
    } else if (pid == 0) {      /* first child */
        if ((pid = fork()) < 0)
            err_sys("fork error");
        else if (pid > 0)
            exit(0);    /* parent from second fork == first child */

        /*
         * We're the second child; our parent becomes init as soon
         * as our real parent calls exit() in the statement above.
         * Here's where we'd continue executing, knowing that when
         * we're done, init will reap our status.
         */
        sleep(2);
        printf("second child, parent pid = %ld\n", (long)getppid());
        exit(0);
    }

    if (waitpid(pid, NULL, 0) != pid)   /* wait for first child */
        err_sys("waitpid error");

    /*
     * We're the parent (the original process); we continue executing,
     * knowing that we're not the parent of the second child.
     */
    exit(0);
}

Problem

Why does grandchild process need to sleep that 2 seconds? Assume it exits before child process exits, it will still be reaped when child process exits according to this question, and parent process still does not need take care of it.

Doesn't that fulfill the original goal of using double fork?


Solution

  • The purpose of the example is to demonstrate that the grandchild's parent becomes process 1 (init) after its original parent exits.

    To demonstrate that the grandchild's parent becomes process 1, the grandchild calls getppid and prints the result.

    1. If the grandchild calls getppid before its original parent has exited, then getppid returns something that's not pid 1.
    2. If the grandchild calls getppid after its original parent has exited, then getppid returns 1.

    The purpose of the example program is to make #2 happen. So it needs to make sure the original parent has exited before the grandchild calls getppid. It does this by calling sleep(2) in the grandchild.

    The grandchild, in a real program, would not sleep(2) there. It would just do its work.

    Since this is a toy program, there's no real work for the grandchild to do.