I am writing a monitoring program in C, which performs the fork()
and exec()
cycle. However I need to check whether the child process has terminated or not without blocking the main process, i.e. the monitoring program. Something like this:
Main process
pid_t child_pid = fork();
if (child_pid == 0)
exec(bar);
while (1) {
if (the child process has finished)
foo();
else
bar();
}
Considering the fact I have the child pid I have tried the following:
Sending a kill
call with signal 0
and examining errno
:
if (kill(child_pid, 0) == -1 || errno == ESRCH)
, which I think is not a good way to track the status of the child process, given that it is not safe from race conditions. Moreover it did not work or at least it seemed so.
Inspecting with stat(2)
whether proc/child_pid
exists. All of the above negative arguments are true in this case as well plus that this method is slower.
waitpid(2)
. Unfortunately it blocks the main process.
Is there any other way to obtain this kind of information? Or perhaps I am missing something from the solutions I have already tried?
More precisely, waitpid() suspends the calling process until the system gets status information on the child. If the system already has status information on an appropriate child when waitpid() is called, waitpid() returns immediately.
Difference between wait and waitpid(): Wait() is a blocking call whereas waipid() can be made non-blocking with WNOHANG option. Wait() waits for any child process but waitpid() waits for a specific child equal to pid.
If any process has no child process then wait() returns immediately “-1”.
The pid parameter specifies the set of child processes for which to wait. If pid is -1, the call waits for any child process.
If you pass WNOHANG
to waitpid
it should not block.
if(waitpid(child_pid, &status, WNOHANG) != 0) {
// child process has finished
foo();
} else {
// child process still running
bar();
}
When a process is terminating, you can set up the parent process to get and handle a SIGCHLD
signal, see signal(7); the signal handler can only call async-signal-safe functions, or set a volatile sigatomic_t
flag tested outside of the handler (e.g. in your main event loop around poll(2)...), or write(2) to some file descriptor (e.g. a pipe or some eventfd(2)). As Bruce Ediger answered you can also use the Linux-specific signalfd
.
Then you can use some waiting function, e.g. waitpid(2) (perhaps with WNOHANG
if you don't want to block) or wait4(2) to wait the process and get its status, etc.
Read also Advanced Linux Programming for more. It has several chapters on these questions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With