Loading debuggerd/backtrace.cpp +3 −1 Original line number Original line Diff line number Diff line Loading @@ -88,7 +88,9 @@ static void dump_thread( return; return; } } wait_for_stop(tid, total_sleep_time_usec); if (!attached && wait_for_sigstop(tid, total_sleep_time_usec, detach_failed) == -1) { return; } UniquePtr<Backtrace> backtrace(Backtrace::Create(tid, BACKTRACE_CURRENT_THREAD)); UniquePtr<Backtrace> backtrace(Backtrace::Create(tid, BACKTRACE_CURRENT_THREAD)); if (backtrace->Unwind(0)) { if (backtrace->Unwind(0)) { Loading debuggerd/debuggerd.cpp +19 −23 Original line number Original line Diff line number Diff line Loading @@ -79,7 +79,7 @@ static void wait_for_user_action(const debugger_request_t &request) { "*\n" "*\n" "* Wait for gdb to start, then press the VOLUME DOWN key\n" "* Wait for gdb to start, then press the VOLUME DOWN key\n" "* to let the process continue crashing.\n" "* to let the process continue crashing.\n" "********************************************************\n", "********************************************************", request.pid, exe, request.tid); request.pid, exe, request.tid); // Wait for VOLUME DOWN. // Wait for VOLUME DOWN. Loading Loading @@ -178,11 +178,11 @@ static int read_request(int fd, debugger_request_t* out_request) { socklen_t len = sizeof(cr); socklen_t len = sizeof(cr); int status = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &len); int status = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &len); if (status != 0) { if (status != 0) { ALOGE("cannot get credentials\n"); ALOGE("cannot get credentials"); return -1; return -1; } } ALOGV("reading tid\n"); ALOGV("reading tid"); fcntl(fd, F_SETFL, O_NONBLOCK); fcntl(fd, F_SETFL, O_NONBLOCK); pollfd pollfds[1]; pollfd pollfds[1]; Loading Loading @@ -279,6 +279,7 @@ static void handle_request(int fd) { ALOGE("ptrace attach failed: %s\n", strerror(errno)); ALOGE("ptrace attach failed: %s\n", strerror(errno)); } else { } else { bool detach_failed = false; bool detach_failed = false; bool tid_unresponsive = false; bool attach_gdb = should_attach_gdb(&request); bool attach_gdb = should_attach_gdb(&request); if (TEMP_FAILURE_RETRY(write(fd, "\0", 1)) != 1) { if (TEMP_FAILURE_RETRY(write(fd, "\0", 1)) != 1) { ALOGE("failed responding to client: %s\n", strerror(errno)); ALOGE("failed responding to client: %s\n", strerror(errno)); Loading @@ -292,8 +293,9 @@ static void handle_request(int fd) { int total_sleep_time_usec = 0; int total_sleep_time_usec = 0; for (;;) { for (;;) { int signal = wait_for_signal(request.tid, &total_sleep_time_usec); int signal = wait_for_sigstop(request.tid, &total_sleep_time_usec, &detach_failed); if (signal < 0) { if (signal == -1) { tid_unresponsive = true; break; break; } } Loading Loading @@ -360,27 +362,21 @@ static void handle_request(int fd) { free(tombstone_path); free(tombstone_path); } } ALOGV("detaching\n"); if (!tid_unresponsive) { ALOGV("detaching"); if (attach_gdb) { if (attach_gdb) { // stop the process so we can debug // stop the process so we can debug kill(request.pid, SIGSTOP); kill(request.pid, SIGSTOP); } // detach so we can attach gdbserver if (ptrace(PTRACE_DETACH, request.tid, 0, 0)) { if (ptrace(PTRACE_DETACH, request.tid, 0, 0)) { ALOGE("ptrace detach from %d failed: %s\n", request.tid, strerror(errno)); ALOGE("ptrace detach from %d failed: %s", request.tid, strerror(errno)); detach_failed = true; detach_failed = true; } } else if (attach_gdb) { // if debug.db.uid is set, its value indicates if we should wait // if debug.db.uid is set, its value indicates if we should wait // for user action for the crashing process. // for user action for the crashing process. // in this case, we log a message and turn the debug LED on // in this case, we log a message and turn the debug LED on // waiting for a gdb connection (for instance) // waiting for a gdb connection (for instance) wait_for_user_action(request); wait_for_user_action(request); } else { // just detach if (ptrace(PTRACE_DETACH, request.tid, 0, 0)) { ALOGE("ptrace detach from %d failed: %s\n", request.tid, strerror(errno)); detach_failed = true; } } } } Loading debuggerd/tombstone.cpp +7 −7 Original line number Original line Diff line number Diff line Loading @@ -374,11 +374,7 @@ static void dump_nearby_maps(BacktraceMap* map, log_t* log, pid_t tid) { } } } } static void dump_thread( static void dump_thread(Backtrace* backtrace, log_t* log) { Backtrace* backtrace, log_t* log, int* total_sleep_time_usec) { wait_for_stop(backtrace->Tid(), total_sleep_time_usec); dump_registers(log, backtrace->Tid()); dump_registers(log, backtrace->Tid()); dump_backtrace_and_stack(backtrace, log); dump_backtrace_and_stack(backtrace, log); Loading Loading @@ -421,13 +417,17 @@ static bool dump_sibling_thread_report( continue; continue; } } if (wait_for_sigstop(new_tid, total_sleep_time_usec, &detach_failed) == -1) { continue; } log->current_tid = new_tid; log->current_tid = new_tid; _LOG(log, logtype::THREAD, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n"); _LOG(log, logtype::THREAD, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n"); dump_thread_info(log, pid, new_tid); dump_thread_info(log, pid, new_tid); UniquePtr<Backtrace> backtrace(Backtrace::Create(pid, new_tid, map)); UniquePtr<Backtrace> backtrace(Backtrace::Create(pid, new_tid, map)); if (backtrace->Unwind(0)) { if (backtrace->Unwind(0)) { dump_thread(backtrace.get(), log, total_sleep_time_usec); dump_thread(backtrace.get(), log); } } log->current_tid = log->crashed_tid; log->current_tid = log->crashed_tid; Loading Loading @@ -628,7 +628,7 @@ static bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal, int si_code UniquePtr<Backtrace> backtrace(Backtrace::Create(pid, tid, map.get())); UniquePtr<Backtrace> backtrace(Backtrace::Create(pid, tid, map.get())); if (backtrace->Unwind(0)) { if (backtrace->Unwind(0)) { dump_abort_message(backtrace.get(), log, abort_msg_address); dump_abort_message(backtrace.get(), log, abort_msg_address); dump_thread(backtrace.get(), log, total_sleep_time_usec); dump_thread(backtrace.get(), log); } } if (want_logs) { if (want_logs) { Loading debuggerd/utility.cpp +25 −29 Original line number Original line Diff line number Diff line Loading @@ -28,8 +28,8 @@ #include <backtrace/Backtrace.h> #include <backtrace/Backtrace.h> #include <log/log.h> #include <log/log.h> const int sleep_time_usec = 50000; // 0.05 seconds const int SLEEP_TIME_USEC = 50000; // 0.05 seconds const int max_total_sleep_usec = 10000000; // 10 seconds const int MAX_TOTAL_SLEEP_USEC = 10000000; // 10 seconds static int write_to_am(int fd, const char* buf, int len) { static int write_to_am(int fd, const char* buf, int len) { int to_write = len; int to_write = len; Loading Loading @@ -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 (;;) { for (;;) { int status; int status; pid_t n = waitpid(tid, &status, __WALL | WNOHANG); pid_t n = TEMP_FAILURE_RETRY(waitpid(tid, &status, __WALL | WNOHANG)); if (n < 0) { if (n == -1) { if (errno == EAGAIN) ALOGE("waitpid failed: tid %d, %s", tid, strerror(errno)); continue; break; ALOGE("waitpid failed: %s\n", strerror(errno)); } else if (n == tid) { return -1; } else if (n > 0) { ALOGV("waitpid: n=%d status=%08x\n", n, status); if (WIFSTOPPED(status)) { if (WIFSTOPPED(status)) { return WSTOPSIG(status); return WSTOPSIG(status); } else { } else { ALOGE("unexpected waitpid response: n=%d, status=%08x\n", n, status); 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) { if (*total_sleep_time_usec > MAX_TOTAL_SLEEP_USEC) { ALOGE("timed out waiting for tid=%d to die\n", tid); ALOGE("timed out waiting for stop signal: tid=%d", tid); return -1; break; } } // not ready yet usleep(SLEEP_TIME_USEC); ALOGV("not ready yet\n"); *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) { if (ptrace(PTRACE_DETACH, tid, 0, 0) != 0) { siginfo_t si; if (allow_dead_tid && errno == ESRCH) { while (TEMP_FAILURE_RETRY(ptrace(PTRACE_GETSIGINFO, tid, 0, &si)) < 0 && errno == ESRCH) { ALOGE("tid exited before attach completed: tid %d", tid); if (*total_sleep_time_usec > max_total_sleep_usec) { } else { ALOGE("timed out waiting for tid=%d to stop\n", tid); *detach_failed = true; break; 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__) #if defined (__mips__) Loading debuggerd/utility.h +2 −3 Original line number Original line Diff line number Diff line Loading @@ -67,12 +67,11 @@ enum logtype { LOGS LOGS }; }; /* Log information onto the tombstone. */ // Log information onto the tombstone. void _LOG(log_t* log, logtype ltype, const char *fmt, ...) void _LOG(log_t* log, logtype ltype, const char *fmt, ...) __attribute__ ((format(printf, 3, 4))); __attribute__ ((format(printf, 3, 4))); int wait_for_signal(pid_t tid, int* total_sleep_time_usec); int wait_for_sigstop(pid_t, int*, bool*); void wait_for_stop(pid_t tid, int* total_sleep_time_usec); void dump_memory(log_t* log, pid_t tid, uintptr_t addr); void dump_memory(log_t* log, pid_t tid, uintptr_t addr); Loading Loading
debuggerd/backtrace.cpp +3 −1 Original line number Original line Diff line number Diff line Loading @@ -88,7 +88,9 @@ static void dump_thread( return; return; } } wait_for_stop(tid, total_sleep_time_usec); if (!attached && wait_for_sigstop(tid, total_sleep_time_usec, detach_failed) == -1) { return; } UniquePtr<Backtrace> backtrace(Backtrace::Create(tid, BACKTRACE_CURRENT_THREAD)); UniquePtr<Backtrace> backtrace(Backtrace::Create(tid, BACKTRACE_CURRENT_THREAD)); if (backtrace->Unwind(0)) { if (backtrace->Unwind(0)) { Loading
debuggerd/debuggerd.cpp +19 −23 Original line number Original line Diff line number Diff line Loading @@ -79,7 +79,7 @@ static void wait_for_user_action(const debugger_request_t &request) { "*\n" "*\n" "* Wait for gdb to start, then press the VOLUME DOWN key\n" "* Wait for gdb to start, then press the VOLUME DOWN key\n" "* to let the process continue crashing.\n" "* to let the process continue crashing.\n" "********************************************************\n", "********************************************************", request.pid, exe, request.tid); request.pid, exe, request.tid); // Wait for VOLUME DOWN. // Wait for VOLUME DOWN. Loading Loading @@ -178,11 +178,11 @@ static int read_request(int fd, debugger_request_t* out_request) { socklen_t len = sizeof(cr); socklen_t len = sizeof(cr); int status = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &len); int status = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &len); if (status != 0) { if (status != 0) { ALOGE("cannot get credentials\n"); ALOGE("cannot get credentials"); return -1; return -1; } } ALOGV("reading tid\n"); ALOGV("reading tid"); fcntl(fd, F_SETFL, O_NONBLOCK); fcntl(fd, F_SETFL, O_NONBLOCK); pollfd pollfds[1]; pollfd pollfds[1]; Loading Loading @@ -279,6 +279,7 @@ static void handle_request(int fd) { ALOGE("ptrace attach failed: %s\n", strerror(errno)); ALOGE("ptrace attach failed: %s\n", strerror(errno)); } else { } else { bool detach_failed = false; bool detach_failed = false; bool tid_unresponsive = false; bool attach_gdb = should_attach_gdb(&request); bool attach_gdb = should_attach_gdb(&request); if (TEMP_FAILURE_RETRY(write(fd, "\0", 1)) != 1) { if (TEMP_FAILURE_RETRY(write(fd, "\0", 1)) != 1) { ALOGE("failed responding to client: %s\n", strerror(errno)); ALOGE("failed responding to client: %s\n", strerror(errno)); Loading @@ -292,8 +293,9 @@ static void handle_request(int fd) { int total_sleep_time_usec = 0; int total_sleep_time_usec = 0; for (;;) { for (;;) { int signal = wait_for_signal(request.tid, &total_sleep_time_usec); int signal = wait_for_sigstop(request.tid, &total_sleep_time_usec, &detach_failed); if (signal < 0) { if (signal == -1) { tid_unresponsive = true; break; break; } } Loading Loading @@ -360,27 +362,21 @@ static void handle_request(int fd) { free(tombstone_path); free(tombstone_path); } } ALOGV("detaching\n"); if (!tid_unresponsive) { ALOGV("detaching"); if (attach_gdb) { if (attach_gdb) { // stop the process so we can debug // stop the process so we can debug kill(request.pid, SIGSTOP); kill(request.pid, SIGSTOP); } // detach so we can attach gdbserver if (ptrace(PTRACE_DETACH, request.tid, 0, 0)) { if (ptrace(PTRACE_DETACH, request.tid, 0, 0)) { ALOGE("ptrace detach from %d failed: %s\n", request.tid, strerror(errno)); ALOGE("ptrace detach from %d failed: %s", request.tid, strerror(errno)); detach_failed = true; detach_failed = true; } } else if (attach_gdb) { // if debug.db.uid is set, its value indicates if we should wait // if debug.db.uid is set, its value indicates if we should wait // for user action for the crashing process. // for user action for the crashing process. // in this case, we log a message and turn the debug LED on // in this case, we log a message and turn the debug LED on // waiting for a gdb connection (for instance) // waiting for a gdb connection (for instance) wait_for_user_action(request); wait_for_user_action(request); } else { // just detach if (ptrace(PTRACE_DETACH, request.tid, 0, 0)) { ALOGE("ptrace detach from %d failed: %s\n", request.tid, strerror(errno)); detach_failed = true; } } } } Loading
debuggerd/tombstone.cpp +7 −7 Original line number Original line Diff line number Diff line Loading @@ -374,11 +374,7 @@ static void dump_nearby_maps(BacktraceMap* map, log_t* log, pid_t tid) { } } } } static void dump_thread( static void dump_thread(Backtrace* backtrace, log_t* log) { Backtrace* backtrace, log_t* log, int* total_sleep_time_usec) { wait_for_stop(backtrace->Tid(), total_sleep_time_usec); dump_registers(log, backtrace->Tid()); dump_registers(log, backtrace->Tid()); dump_backtrace_and_stack(backtrace, log); dump_backtrace_and_stack(backtrace, log); Loading Loading @@ -421,13 +417,17 @@ static bool dump_sibling_thread_report( continue; continue; } } if (wait_for_sigstop(new_tid, total_sleep_time_usec, &detach_failed) == -1) { continue; } log->current_tid = new_tid; log->current_tid = new_tid; _LOG(log, logtype::THREAD, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n"); _LOG(log, logtype::THREAD, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n"); dump_thread_info(log, pid, new_tid); dump_thread_info(log, pid, new_tid); UniquePtr<Backtrace> backtrace(Backtrace::Create(pid, new_tid, map)); UniquePtr<Backtrace> backtrace(Backtrace::Create(pid, new_tid, map)); if (backtrace->Unwind(0)) { if (backtrace->Unwind(0)) { dump_thread(backtrace.get(), log, total_sleep_time_usec); dump_thread(backtrace.get(), log); } } log->current_tid = log->crashed_tid; log->current_tid = log->crashed_tid; Loading Loading @@ -628,7 +628,7 @@ static bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal, int si_code UniquePtr<Backtrace> backtrace(Backtrace::Create(pid, tid, map.get())); UniquePtr<Backtrace> backtrace(Backtrace::Create(pid, tid, map.get())); if (backtrace->Unwind(0)) { if (backtrace->Unwind(0)) { dump_abort_message(backtrace.get(), log, abort_msg_address); dump_abort_message(backtrace.get(), log, abort_msg_address); dump_thread(backtrace.get(), log, total_sleep_time_usec); dump_thread(backtrace.get(), log); } } if (want_logs) { if (want_logs) { Loading
debuggerd/utility.cpp +25 −29 Original line number Original line Diff line number Diff line Loading @@ -28,8 +28,8 @@ #include <backtrace/Backtrace.h> #include <backtrace/Backtrace.h> #include <log/log.h> #include <log/log.h> const int sleep_time_usec = 50000; // 0.05 seconds const int SLEEP_TIME_USEC = 50000; // 0.05 seconds const int max_total_sleep_usec = 10000000; // 10 seconds const int MAX_TOTAL_SLEEP_USEC = 10000000; // 10 seconds static int write_to_am(int fd, const char* buf, int len) { static int write_to_am(int fd, const char* buf, int len) { int to_write = len; int to_write = len; Loading Loading @@ -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 (;;) { for (;;) { int status; int status; pid_t n = waitpid(tid, &status, __WALL | WNOHANG); pid_t n = TEMP_FAILURE_RETRY(waitpid(tid, &status, __WALL | WNOHANG)); if (n < 0) { if (n == -1) { if (errno == EAGAIN) ALOGE("waitpid failed: tid %d, %s", tid, strerror(errno)); continue; break; ALOGE("waitpid failed: %s\n", strerror(errno)); } else if (n == tid) { return -1; } else if (n > 0) { ALOGV("waitpid: n=%d status=%08x\n", n, status); if (WIFSTOPPED(status)) { if (WIFSTOPPED(status)) { return WSTOPSIG(status); return WSTOPSIG(status); } else { } else { ALOGE("unexpected waitpid response: n=%d, status=%08x\n", n, status); 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) { if (*total_sleep_time_usec > MAX_TOTAL_SLEEP_USEC) { ALOGE("timed out waiting for tid=%d to die\n", tid); ALOGE("timed out waiting for stop signal: tid=%d", tid); return -1; break; } } // not ready yet usleep(SLEEP_TIME_USEC); ALOGV("not ready yet\n"); *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) { if (ptrace(PTRACE_DETACH, tid, 0, 0) != 0) { siginfo_t si; if (allow_dead_tid && errno == ESRCH) { while (TEMP_FAILURE_RETRY(ptrace(PTRACE_GETSIGINFO, tid, 0, &si)) < 0 && errno == ESRCH) { ALOGE("tid exited before attach completed: tid %d", tid); if (*total_sleep_time_usec > max_total_sleep_usec) { } else { ALOGE("timed out waiting for tid=%d to stop\n", tid); *detach_failed = true; break; 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__) #if defined (__mips__) Loading
debuggerd/utility.h +2 −3 Original line number Original line Diff line number Diff line Loading @@ -67,12 +67,11 @@ enum logtype { LOGS LOGS }; }; /* Log information onto the tombstone. */ // Log information onto the tombstone. void _LOG(log_t* log, logtype ltype, const char *fmt, ...) void _LOG(log_t* log, logtype ltype, const char *fmt, ...) __attribute__ ((format(printf, 3, 4))); __attribute__ ((format(printf, 3, 4))); int wait_for_signal(pid_t tid, int* total_sleep_time_usec); int wait_for_sigstop(pid_t, int*, bool*); void wait_for_stop(pid_t tid, int* total_sleep_time_usec); void dump_memory(log_t* log, pid_t tid, uintptr_t addr); void dump_memory(log_t* log, pid_t tid, uintptr_t addr); Loading