From c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5 Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Mon, 13 Feb 2017 16:36:18 -0800 Subject: [PATCH] debuggerd_handler: don't use waitpid(..., __WCLONE). waitpid(..., __WCLONE) fails with ECHILD when passed an explicit PID to wait for. __WALL and __WCLONE don't seem to be necessary when waiting for a specific pid, so just pass 0 in the flags instead. Bug: http://b/35327712 Test: /data/nativetest/debuggerd_test/debuggerd_test32 --gtest_filter="*zombie*" Change-Id: I3dd7a1bdf7ff35fdfbf631429c089ef4e3172855 --- debuggerd/debuggerd_test.cpp | 32 +++++++++++++++++++++++++ debuggerd/handler/debuggerd_handler.cpp | 2 +- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp index 002e940d9..e22d6a9d3 100644 --- a/debuggerd/debuggerd_test.cpp +++ b/debuggerd/debuggerd_test.cpp @@ -407,3 +407,35 @@ TEST_F(CrasherTest, PR_SET_DUMPABLE_0_raise) { }); AssertDeath(SIGUSR1); } + +TEST(crash_dump, zombie) { + pid_t forkpid = fork(); + + int pipefd[2]; + ASSERT_EQ(0, pipe2(pipefd, O_CLOEXEC)); + + pid_t rc; + int status; + + if (forkpid == 0) { + errno = 0; + rc = waitpid(-1, &status, WNOHANG | __WALL | __WNOTHREAD); + if (rc != -1 || errno != ECHILD) { + errx(2, "first waitpid returned %d (%s), expected failure with ECHILD", rc, strerror(errno)); + } + + raise(DEBUGGER_SIGNAL); + + errno = 0; + rc = waitpid(-1, &status, __WALL | __WNOTHREAD); + if (rc != -1 || errno != ECHILD) { + errx(2, "second waitpid returned %d (%s), expected failure with ECHILD", rc, strerror(errno)); + } + _exit(0); + } else { + rc = waitpid(forkpid, &status, 0); + ASSERT_EQ(forkpid, rc); + ASSERT_TRUE(WIFEXITED(status)); + ASSERT_EQ(0, WEXITSTATUS(status)); + } +} diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp index 38a7be35f..353f642a8 100644 --- a/debuggerd/handler/debuggerd_handler.cpp +++ b/debuggerd/handler/debuggerd_handler.cpp @@ -249,7 +249,7 @@ static int debuggerd_dispatch_pseudothread(void* arg) { // Don't leave a zombie child. int status; - if (TEMP_FAILURE_RETRY(waitpid(forkpid, &status, __WCLONE)) == -1 && errno != ECHILD) { + if (TEMP_FAILURE_RETRY(waitpid(forkpid, &status, 0)) == -1) { __libc_format_log(ANDROID_LOG_FATAL, "libc", "failed to wait for crash_dump helper: %s", strerror(errno)); } else if (WIFSTOPPED(status) || WIFSIGNALED(status)) {