Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Monitor if a process has terminated in C

Introduction

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();
}

What I have tried

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.

The question

Is there any other way to obtain this kind of information? Or perhaps I am missing something from the solutions I have already tried?

like image 387
0x450 Avatar asked Jul 27 '15 16:07

0x450


People also ask

What does Waitpid do in C?

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.

What is the difference between wait and waitpid?

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.

What value is returned by wait() when the child process exits?

If any process has no child process then wait() returns immediately “-1”.

What does Waitpid 1 mean?

The pid parameter specifies the set of child processes for which to wait. If pid is -1, the call waits for any child process.


2 Answers

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();
}
like image 53
Eric Renouf Avatar answered Oct 14 '22 04:10

Eric Renouf


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.

like image 45
Basile Starynkevitch Avatar answered Oct 14 '22 06:10

Basile Starynkevitch