diff --git a/daemon/external-helper.c b/daemon/external-helper.c index ca19e96..18335d8 100644 --- a/daemon/external-helper.c +++ b/daemon/external-helper.c @@ -37,6 +37,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include /** @@ -47,6 +48,16 @@ int run_external_process(const char *const *exec_args) pid_t p; int status = 0; + /* set up our signaling for the child and the timout */ + sigset_t mask; + sigset_t omask; + sigemptyset(&mask); + sigaddset(&mask, SIGCHLD); + if (sigprocmask(SIG_BLOCK, &mask, &omask) < 0) { + LOG_ERROR("sigprocmask failed: %s\n", strerror(errno)); + return -1; + } + if ((p = fork()) < 0) { LOG_ERROR("Failed to fork(): %s\n", strerror(errno)); return false; @@ -65,6 +76,27 @@ int run_external_process(const char *const *exec_args) _exit(EXIT_SUCCESS); } + /* Set up the timout */ + struct timespec timeout; + timeout.tv_sec = 5; /* Magic timeout value of 5s for now - should be sane for most commands */ + timeout.tv_nsec = 0; + + /* Wait for the child to finish up with a timout */ + while (true) { + if (sigtimedwait(&mask, NULL, &timeout) < 0) { + if (errno == EINTR) { + continue; + } else if (errno == EAGAIN) { + LOG_ERROR("Child process timed out for %s, killing and returning\n", exec_args[0]); + kill(p, SIGKILL); + } else { + LOG_ERROR("sigtimedwait failed: %s\n", strerror(errno)); + return -1; + } + } + break; + } + if (waitpid(p, &status, 0) < 0) { LOG_ERROR("Failed to waitpid(%d): %s\n", (int)p, strerror(errno)); return -1;