Reputation: 14719
I got the PID of a process and I need to check if it is a zombie using POSIX system calls in C. How should I do that?
The problem I'm having is that I have a process and it forks into many children, the children all do execs and sometimes I want to do the exec in background so I can't really wait() the children that go in background. I could wait() periodically (once in my main loop) but I need to know which processes are zombie so my father process doesn't hang while waiting for children that are not going to end soon.
If you are curious, I'm building a unix shell and it is in the shell nature to have the children processes behaving asynchronously.
Upvotes: 4
Views: 8447
Reputation: 21
And what about the shell command 'ps' which shows you the table of active processes where you can find that an process is 'defunct'? I suppose there must be a way to get that information from c code.
Upvotes: 0
Reputation: 753655
Normally, the shell checks for defunct children shortly before printing its prompt - using the waitpid(2)
system call and the WNOHANG
option as already discussed. You might also want a SIGCHLD handler - but you'd have to decide what you're going to do with the information if you're busy waiting for some foreground process to terminate and it is actually a background process that terminates.
This is only a minor variation on the currently selected answer.
Upvotes: 1
Reputation: 146043
But .. but .. the zombie is a child (at some level) and the process that's checking is a parent, right? So if you are concerned that a specific pid is a zombie why not just do a waitpid(2)
with WNOHANG
and get rid of it? Now, this will consume the exit status, so it may be a bad idea if some other process might want to really wait
in the future.
Upvotes: 3
Reputation: 6163
You mention that you are building a Unix shell; you should read this: Proper handling of SIGINT/SIGQUIT
Upvotes: 1
Reputation: 231103
You can't check whether a process is a zombie with pure POSIX calls - except where you're the parent process, and reaping it with a wait
family call. So you'll have to find a good place to wait for the child.
One option is to set a SIGCHLD
handler and do a waitpid(0, &status, WNOHANG)
there. Be sure to loop until it no longer finds any processes - if two children die within a short interval, you may only get one SIGCHLD
.
Another option is to double fork - that is, fork()
, have the child (call it child A) fork again, have the second child (child B) exec. Then child A immediately exits. Meanwhile the parent is wait()
ing for child A. Once child A is gone, the system's init process will take care of reaping child B when it eventually dies. This method is simpler, but your shell will have no way of knowing when child B dies, so if you need that information, use the former method.
Upvotes: 6