diff options
author | Daniel Lezcano <daniel.lezcano@linaro.org> | 2014-03-31 18:32:09 +0200 |
---|---|---|
committer | Daniel Lezcano <daniel.lezcano@free.fr> | 2014-05-27 11:07:49 +0200 |
commit | a8686380af4b81435a91b364a94397c6bd4ec1d6 (patch) | |
tree | 7894953c4a6907e24843b7319119e30f02d111a8 | |
parent | e845c09ff297bf16a904cfe9e18a01b8cb635ac5 (diff) |
idlestat: add timeout for the exec'ed command
Add a timeout for the specified command.
The timeout option is shared with the -t option. When no command line has to be
executed, the timeout becomes the duration of the acquisition, otherwise the
command is executed during an amount of time and terminated if the timeout
occur.
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
-rw-r--r-- | idlestat.c | 36 |
1 files changed, 34 insertions, 2 deletions
@@ -25,6 +25,7 @@ * */ #define _GNU_SOURCE +#include <errno.h> #include <getopt.h> #include <stdio.h> #include <stdlib.h> @@ -1116,6 +1117,14 @@ static int idlestat_wake_all(void) return 0; } +static volatile sig_atomic_t sigalrm = 0; + +static void sighandler(int sig) +{ + if (sig == SIGALRM) + sigalrm = 1; +} + static int execute(int argc, char *argv[], char *const envp[], struct idledebug_options *options) { @@ -1138,9 +1147,32 @@ static int execute(int argc, char *argv[], char *const envp[], } if (pid) { - waitpid(pid, &status, 0); - if (WIFEXITED(status) && !WEXITSTATUS(status)) + struct sigaction s = { + .sa_handler = sighandler, + .sa_flags = SA_RESETHAND, + }; + + sigaddset(&s.sa_mask, SIGALRM); + sigaction(SIGALRM, &s, NULL); + alarm(options->duration); + again: + if (waitpid(pid, &status, 0) < 0) { + if (errno != EINTR || !sigalrm) + goto again; + kill(pid, SIGTERM); + } + + if (WIFEXITED(status) && !WEXITSTATUS(status)) { + /* + * Cancel the timer in case the program + * finished before the timeout + */ + alarm(0); + return 0; + } + + if (WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM) return 0; } |