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;
}
Yes,
waitpidwill 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 callswaitpid(or anotherwait-family function) or until the parent exits (at which point the status is collected by theinitprocess). 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 callwaitpidtwice is simply becausewaitpidwill not modify thestatusargument ifpidno longer exists. So the first call should be working and filling instatus, and the second call should be returning an error code and not changingstatus. You can verify this by inspecting the return values of thewaitpidcalls and/or using two differentstatusvariables.