From: Daniel Lezcano daniel.lezcano@linaro.org
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 --- idlestat.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-)
diff --git a/idlestat.c b/idlestat.c index 7ed9f85..d9ce30a 100644 --- a/idlestat.c +++ b/idlestat.c @@ -25,6 +25,7 @@ * */ #define _GNU_SOURCE +#include <errno.h> #include <getopt.h> #include <stdio.h> #include <stdlib.h> @@ -1126,6 +1127,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) { @@ -1148,9 +1157,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; }