diff options
author | Christopher Ferris <cferris@google.com> | 2015-01-30 11:00:52 -0800 |
---|---|---|
committer | Christopher Ferris <cferris@google.com> | 2015-02-03 14:53:44 -0800 |
commit | 1a9a3386151d90152cc18d995b9877b50ca84d90 (patch) | |
tree | 2c152cba09dc3af862eb411e2961476cccb07d58 /cmds/dumpstate | |
parent | 51bfedd821c79ae34ee1caffd9ae958faa71ecec (diff) | |
download | frameworks_native-1a9a3386151d90152cc18d995b9877b50ca84d90.zip frameworks_native-1a9a3386151d90152cc18d995b9877b50ca84d90.tar.gz frameworks_native-1a9a3386151d90152cc18d995b9877b50ca84d90.tar.bz2 |
Add better timeout mechanism for running commands.
Change-Id: I60fc9e7d59c3e0e4b8b2f69f79c6903240bfd131
Diffstat (limited to 'cmds/dumpstate')
-rw-r--r-- | cmds/dumpstate/utils.c | 87 |
1 files changed, 69 insertions, 18 deletions
diff --git a/cmds/dumpstate/utils.c b/cmds/dumpstate/utils.c index 3e0b24b..6beb5ed 100644 --- a/cmds/dumpstate/utils.c +++ b/cmds/dumpstate/utils.c @@ -301,6 +301,50 @@ static int64_t nanotime() { return (int64_t)ts.tv_sec * NANOS_PER_SEC + ts.tv_nsec; } +bool waitpid_with_timeout(pid_t pid, int timeout_seconds, int* status) { + sigset_t child_mask, old_mask; + sigemptyset(&child_mask); + sigaddset(&child_mask, SIGCHLD); + + if (sigprocmask(SIG_BLOCK, &child_mask, &old_mask) == -1) { + printf("*** sigprocmask failed: %s\n", strerror(errno)); + return false; + } + + struct timespec ts; + ts.tv_sec = timeout_seconds; + ts.tv_nsec = 0; + int ret = TEMP_FAILURE_RETRY(sigtimedwait(&child_mask, NULL, &ts)); + int saved_errno = errno; + // Set the signals back the way they were. + if (sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) { + printf("*** sigprocmask failed: %s\n", strerror(errno)); + if (ret == 0) { + return false; + } + } + if (ret == -1) { + errno = saved_errno; + if (errno == EAGAIN) { + errno = ETIMEDOUT; + } else { + printf("*** sigtimedwait failed: %s\n", strerror(errno)); + } + return false; + } + + pid_t child_pid = waitpid(pid, status, WNOHANG); + if (child_pid != pid) { + if (child_pid != -1) { + printf("*** Waiting for pid %d, got pid %d instead\n", pid, child_pid); + } else { + printf("*** waitpid failed: %s\n", strerror(errno)); + } + return false; + } + return true; +} + /* forks a command and waits for it to finish */ int run_command(const char *title, int timeout_seconds, const char *command, ...) { fflush(stdout); @@ -345,28 +389,35 @@ int run_command(const char *title, int timeout_seconds, const char *command, ... } /* handle parent case */ - for (;;) { - int status; - pid_t p = waitpid(pid, &status, WNOHANG); - int64_t elapsed = nanotime() - start; - if (p == pid) { - if (WIFSIGNALED(status)) { - printf("*** %s: Killed by signal %d\n", command, WTERMSIG(status)); - } else if (WIFEXITED(status) && WEXITSTATUS(status) > 0) { - printf("*** %s: Exit code %d\n", command, WEXITSTATUS(status)); - } - if (title) printf("[%s: %.3fs elapsed]\n\n", command, (float)elapsed / NANOS_PER_SEC); - return status; + int status; + bool ret = waitpid_with_timeout(pid, timeout_seconds, &status); + uint64_t elapsed = nanotime() - start; + if (!ret) { + if (errno == ETIMEDOUT) { + printf("*** %s: Timed out after %.3fs (killing pid %d)\n", command, + (float) elapsed / NANOS_PER_SEC, pid); + } else { + printf("*** %s: Error after %.4fs (killing pid %d)\n", command, + (float) elapsed / NANOS_PER_SEC, pid); } - - if (timeout_seconds && elapsed / NANOS_PER_SEC > timeout_seconds) { - printf("*** %s: Timed out after %.3fs (killing pid %d)\n", command, (float) elapsed / NANOS_PER_SEC, pid); - kill(pid, SIGTERM); - return -1; + kill(pid, SIGTERM); + if (!waitpid_with_timeout(pid, 5, NULL)) { + kill(pid, SIGKILL); + if (!waitpid_with_timeout(pid, 5, NULL)) { + printf("*** %s: Cannot kill %d even with SIGKILL.\n", command, pid); + } } + return -1; + } - usleep(100000); // poll every 0.1 sec + if (WIFSIGNALED(status)) { + printf("*** %s: Killed by signal %d\n", command, WTERMSIG(status)); + } else if (WIFEXITED(status) && WEXITSTATUS(status) > 0) { + printf("*** %s: Exit code %d\n", command, WEXITSTATUS(status)); } + if (title) printf("[%s: %.3fs elapsed]\n\n", command, (float)elapsed / NANOS_PER_SEC); + + return status; } size_t num_props = 0; |