summaryrefslogtreecommitdiffstats
path: root/debuggerd/utility.cpp
diff options
context:
space:
mode:
authorChristopher Ferris <cferris@google.com>2014-10-31 21:34:38 -0700
committerChristopher Ferris <cferris@google.com>2014-11-03 11:26:33 -0800
commit1072f917cfa36ff905c31122a3cd99224e305932 (patch)
treed3891827ac393205351b6230e0d2b182ce5e3eae /debuggerd/utility.cpp
parentcb8c583d493a98cd1499c64e7c68f3ac37ebb7cd (diff)
downloadsystem_core-1072f917cfa36ff905c31122a3cd99224e305932.tar.gz
system_core-1072f917cfa36ff905c31122a3cd99224e305932.tar.bz2
system_core-1072f917cfa36ff905c31122a3cd99224e305932.zip
Fix debuggerd issues.
- Fix a problem where a tid exits before the attach completes, and it causes debuggerd to self terminate. - Fix a problem where sibling tid dumps do not properly wait for the tid to get signalled. Bug: 17800180 Bug: 12567315 (cherry picked from commit 84ddb34a3af77dbe490aaa07b738bbfd7109d5ba) Change-Id: I45e33865614d4c96f4a89cf117398666b556d500
Diffstat (limited to 'debuggerd/utility.cpp')
-rw-r--r--debuggerd/utility.cpp54
1 files changed, 25 insertions, 29 deletions
diff --git a/debuggerd/utility.cpp b/debuggerd/utility.cpp
index 9a30fe3de..2baf9de19 100644
--- a/debuggerd/utility.cpp
+++ b/debuggerd/utility.cpp
@@ -28,8 +28,8 @@
#include <backtrace/Backtrace.h>
#include <log/log.h>
-const int sleep_time_usec = 50000; // 0.05 seconds
-const int max_total_sleep_usec = 10000000; // 10 seconds
+const int SLEEP_TIME_USEC = 50000; // 0.05 seconds
+const int MAX_TOTAL_SLEEP_USEC = 10000000; // 10 seconds
static int write_to_am(int fd, const char* buf, int len) {
int to_write = len;
@@ -91,48 +91,44 @@ void _LOG(log_t* log, enum logtype ltype, const char* fmt, ...) {
}
}
-int wait_for_signal(pid_t tid, int* total_sleep_time_usec) {
+int wait_for_sigstop(pid_t tid, int* total_sleep_time_usec, bool* detach_failed) {
+ bool allow_dead_tid = false;
for (;;) {
int status;
- pid_t n = waitpid(tid, &status, __WALL | WNOHANG);
- if (n < 0) {
- if (errno == EAGAIN)
- continue;
- ALOGE("waitpid failed: %s\n", strerror(errno));
- return -1;
- } else if (n > 0) {
- ALOGV("waitpid: n=%d status=%08x\n", n, status);
+ pid_t n = TEMP_FAILURE_RETRY(waitpid(tid, &status, __WALL | WNOHANG));
+ if (n == -1) {
+ ALOGE("waitpid failed: tid %d, %s", tid, strerror(errno));
+ break;
+ } else if (n == tid) {
if (WIFSTOPPED(status)) {
return WSTOPSIG(status);
} else {
ALOGE("unexpected waitpid response: n=%d, status=%08x\n", n, status);
- return -1;
+ // This is the only circumstance under which we can allow a detach
+ // to fail with ESRCH, which indicates the tid has exited.
+ allow_dead_tid = true;
+ break;
}
}
- if (*total_sleep_time_usec > max_total_sleep_usec) {
- ALOGE("timed out waiting for tid=%d to die\n", tid);
- return -1;
+ if (*total_sleep_time_usec > MAX_TOTAL_SLEEP_USEC) {
+ ALOGE("timed out waiting for stop signal: tid=%d", tid);
+ break;
}
- // not ready yet
- ALOGV("not ready yet\n");
- usleep(sleep_time_usec);
- *total_sleep_time_usec += sleep_time_usec;
+ usleep(SLEEP_TIME_USEC);
+ *total_sleep_time_usec += SLEEP_TIME_USEC;
}
-}
-void wait_for_stop(pid_t tid, int* total_sleep_time_usec) {
- siginfo_t si;
- while (TEMP_FAILURE_RETRY(ptrace(PTRACE_GETSIGINFO, tid, 0, &si)) < 0 && errno == ESRCH) {
- if (*total_sleep_time_usec > max_total_sleep_usec) {
- ALOGE("timed out waiting for tid=%d to stop\n", tid);
- break;
+ if (ptrace(PTRACE_DETACH, tid, 0, 0) != 0) {
+ if (allow_dead_tid && errno == ESRCH) {
+ ALOGE("tid exited before attach completed: tid %d", tid);
+ } else {
+ *detach_failed = true;
+ ALOGE("detach failed: tid %d, %s", tid, strerror(errno));
}
-
- usleep(sleep_time_usec);
- *total_sleep_time_usec += sleep_time_usec;
}
+ return -1;
}
#if defined (__mips__)