Skip to content

Instantly share code, notes, and snippets.

@aktau
Last active December 16, 2015 09:19
Show Gist options
  • Save aktau/5412466 to your computer and use it in GitHub Desktop.
Save aktau/5412466 to your computer and use it in GitHub Desktop.
waitpidTimeout
/**
* Wait (block) a maximum amount of time before forcefully killing a child (worker) and returning
*
* NOTE: this could interact badly if SIGCHLD is handled by a signal handler, such is the case
* with this particular codebase. The reason is that the wait() might not be triggered anymore
* because the PID in question was already waited on in the signal handler.
*/
static void ctlWaitPidTimeout(pid_t worker_pid, useconds_t usec) {
TRACE("ctlWaitPidTimeout: waiting on %lu\n", (unsigned long) worker_pid);
/* create child that will time out */
pid_t timeout_pid = fork();
if (timeout_pid == 0) {
usleep(usec);
TRACE("ctlWaitPidTimeout: [WARNING] timing out!\n");
_exit(0);
}
/* wait for either the timeout child to time out or the actual process that is being killed */
pid_t exited_pid = wait(NULL);
/* whatever child just exited, kill the other one for good measure */
if (exited_pid == worker_pid) {
TRACE("ctlWaitPidTimeout: worker pid exited, excellent\n");
kill(timeout_pid, SIGKILL);
}
else {
TRACE("ctlWaitPidTimeout: timeout pid exited, will have to terminate worker the hard way\n");
kill(worker_pid, SIGKILL);
}
/* wait for the child we just killed */
wait(NULL);
TRACE("ctlWaitPidTimeout: timeout wait done\n");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment