summaryrefslogtreecommitdiffstats
path: root/debuggerd/handler/debuggerd_handler.cpp
diff options
context:
space:
mode:
authorJosh Gao <jmgao@google.com>2017-02-01 17:43:14 -0800
committerJosh Gao <jmgao@google.com>2017-02-02 13:54:39 -0800
commitb3ee52e4d0ee6f52c78d5f12cdc551686b1ebba7 (patch)
tree11ac8fedec1ef5e808019f9153e88f1395469ad5 /debuggerd/handler/debuggerd_handler.cpp
parent85bcaf68d33ac0d92df0a3aa6ce34a09b382a9e6 (diff)
downloadsystem_core-b3ee52e4d0ee6f52c78d5f12cdc551686b1ebba7.tar.gz
system_core-b3ee52e4d0ee6f52c78d5f12cdc551686b1ebba7.tar.bz2
system_core-b3ee52e4d0ee6f52c78d5f12cdc551686b1ebba7.zip
debuggerd_handler: don't use clone(..., SIGCHLD, ...)
Processes that handle SIGCHLD can race with the crash handler to wait on the crash_dump process. Use clone flags that cause the forked child's death to not be reported via SIGCHLD, and don't bail out of dumping when waitpid returns ECHILD (in case another thread is already in a waitpid(..., __WALL)) Note that the use of waitid was switched to waitpid, because waitid doesn't support __WCLONE until kernel version 4.7. Bug: none Test: "debuggerd -b `pidof zygote64`" a few times (failed roughly 50% of the time previously) Change-Id: Ia41a26a61f13c6f9aa85c4c2f88aef8d279d35ad
Diffstat (limited to 'debuggerd/handler/debuggerd_handler.cpp')
-rw-r--r--debuggerd/handler/debuggerd_handler.cpp8
1 files changed, 5 insertions, 3 deletions
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index 4cc077dcc..21cc0c771 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -197,7 +197,7 @@ static int debuggerd_dispatch_pseudothread(void* arg) {
}
// Don't use fork(2) to avoid calling pthread_atfork handlers.
- int forkpid = clone(nullptr, nullptr, SIGCHLD, nullptr);
+ int forkpid = clone(nullptr, nullptr, 0, nullptr);
if (forkpid == -1) {
__libc_format_log(ANDROID_LOG_FATAL, "libc", "failed to fork in debuggerd signal handler: %s",
strerror(errno));
@@ -237,10 +237,12 @@ static int debuggerd_dispatch_pseudothread(void* arg) {
close(pipefds[0]);
// Don't leave a zombie child.
- siginfo_t child_siginfo;
- if (TEMP_FAILURE_RETRY(waitid(P_PID, forkpid, &child_siginfo, WEXITED)) != 0) {
+ int status;
+ if (TEMP_FAILURE_RETRY(waitpid(forkpid, &status, __WCLONE)) == -1 && errno != ECHILD) {
__libc_format_log(ANDROID_LOG_FATAL, "libc", "failed to wait for crash_dump helper: %s",
strerror(errno));
+ } else if (WIFSTOPPED(status) || WIFSIGNALED(status)) {
+ __libc_format_log(ANDROID_LOG_FATAL, "libc", "crash_dump helper crashed or stopped");
thread_info->crash_dump_started = false;
}
}