views:

63

answers:

3

If I fork a child process, and the child process exits before the parent calls waitpid, then is the exit status information that is set by waitpid still valid? If so, when does it become not valid; i.e., how do I ensure that I can call waitpid on the child pid and continue to get valid exit status information after an arbitrary amount of time, and how do I "clean up" (tell the OS that I am no longer interested in the exit status information for the finished child process)?

I was playing around with the following code, and it appears that the exit status information is valid for at least a few seconds after the child finishes, but I do not know for how long or how to inform the OS that I won't be calling waitpid again:

#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main()
{
    pid_t pid = fork();

    if (pid < 0) {
        fprintf(stderr, "Failed to fork\n");
        return EXIT_FAILURE;
    }
    else if (pid == 0) { // code for child process
        _exit(17);
    }
    else { // code for parent
        sleep(3);

        int status;
        waitpid(pid, &status, 0);
        waitpid(pid, &status, 0); // call `waitpid` again just to see if the first call had an effect
        assert(WIFEXITED(status));
        assert(WEXITSTATUS(status) == 17);
    }

    return EXIT_SUCCESS;
}
+4  A: 

Yes, waitpid will work after the child has exited. The OS will keep a child process' entry in the process table (including exit status) around until the parent calls waitpid (or another wait-family function) or until the parent exits (at which point the status is collected by the init process). This is what a "zombie" process is: a process that has exited by is still resident in the process table for exactly this purpose.

The process' entry in the table should go away after the first call to waitpid. I suspect the reason that in your example you seem to be able to call waitpid twice is simply because waitpid will not modify the status argument if pid no longer exists. So the first call should be working and filling in status, and the second call should be returning an error code and not changing status. You can verify this by inspecting the return values of the waitpid calls and/or using two different status variables.

Tyler McHenry
Indeed, the second `waitpid` call did fail. I didn't think about that! Thank you for pointing this out.
Daniel Trebbien
+3  A: 

The OS keeps terminated process in a zombie state until its parent (which might be the init if the original parent process terminated earlier) collects that exit status with wait(2) system call. So the answer is - the exit status of the process does not become invalid.

Nikolai N Fetissov
+2  A: 

Yes.

From the man page:

A child that terminates, but has not been waited for becomes a "zombie". The kernel maintains a minimal set of information about the zombie process (PID, termination status, resource usage information) in order to allow the parent to later perform a wait to obtain information about the child.

unwind