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 (pi开发者_如何学JAVAd == 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, 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.
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.
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.
精彩评论