From 5f2ff6a9106083e2a79b8600a0bf6a5341c6ca38 Mon Sep 17 00:00:00 2001 From: Christopher Ferris Date: Tue, 13 Jan 2015 19:07:12 -0800 Subject: [PATCH] Add timed versions of stack dumping functions. Under some unknown circumstances, debuggerd could become unresponsive. If you try and take a bugreport during this time, it will hang forever. Adding functions that have a timeout will allow dumpstate to stop if dumping is taking too long. Bug: 18766581 Change-Id: I85053b8dcfe6224e2b64b4d8f7f2ef448b3cda34 --- include/cutils/debugger.h | 15 +++++++++++++++ libcutils/debugger.c | 32 +++++++++++++++++++++++++++++--- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/include/cutils/debugger.h b/include/cutils/debugger.h index 4bcc8e6b4..bae687d61 100644 --- a/include/cutils/debugger.h +++ b/include/cutils/debugger.h @@ -64,11 +64,26 @@ typedef struct { */ int dump_tombstone(pid_t tid, char* pathbuf, size_t pathlen); +/* Dumps a process backtrace, registers, and stack to a tombstone file (requires root). + * Stores the tombstone path in the provided buffer. + * If reading debugger data from debuggerd ever takes longer than timeout_secs + * seconds, then stop and return an error. + * Returns 0 on success, -1 on error. + */ +int dump_tombstone_timeout(pid_t tid, char* pathbuf, size_t pathlen, int timeout_secs); + /* Dumps a process backtrace only to the specified file (requires root). * Returns 0 on success, -1 on error. */ int dump_backtrace_to_file(pid_t tid, int fd); +/* Dumps a process backtrace only to the specified file (requires root). + * If reading debugger data from debuggerd ever takes longer than timeout_secs + * seconds, then stop and return an error. + * Returns 0 on success, -1 on error. + */ +int dump_backtrace_to_file_timeout(pid_t tid, int fd, int timeout_secs); + #ifdef __cplusplus } #endif diff --git a/libcutils/debugger.c b/libcutils/debugger.c index 4035ee160..b8a2efc49 100644 --- a/libcutils/debugger.c +++ b/libcutils/debugger.c @@ -19,11 +19,16 @@ #include #include #include +#include +#include #include #include #include +#define LOG_TAG "DEBUG" +#include + #if defined(__LP64__) #include @@ -64,7 +69,7 @@ static int send_request(int sock_fd, void* msg_ptr, size_t msg_len) { return result; } -static int make_dump_request(debugger_action_t action, pid_t tid) { +static int make_dump_request(debugger_action_t action, pid_t tid, int timeout_secs) { const char* socket_name; debugger_msg_t msg; size_t msg_len; @@ -98,6 +103,19 @@ static int make_dump_request(debugger_action_t action, pid_t tid) { return -1; } + if (timeout_secs > 0) { + struct timeval tm; + tm.tv_sec = timeout_secs; + tm.tv_usec = 0; + if (setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &tm, sizeof(tm)) == -1) { + ALOGE("WARNING: Cannot set receive timeout value on socket: %s", strerror(errno)); + } + + if (setsockopt(sock_fd, SOL_SOCKET, SO_SNDTIMEO, &tm, sizeof(tm)) == -1) { + ALOGE("WARNING: Cannot set send timeout value on socket: %s", strerror(errno)); + } + } + if (send_request(sock_fd, msg_ptr, msg_len) < 0) { TEMP_FAILURE_RETRY(close(sock_fd)); return -1; @@ -107,7 +125,11 @@ static int make_dump_request(debugger_action_t action, pid_t tid) { } int dump_backtrace_to_file(pid_t tid, int fd) { - int sock_fd = make_dump_request(DEBUGGER_ACTION_DUMP_BACKTRACE, tid); + return dump_backtrace_to_file_timeout(tid, fd, 0); +} + +int dump_backtrace_to_file_timeout(pid_t tid, int fd, int timeout_secs) { + int sock_fd = make_dump_request(DEBUGGER_ACTION_DUMP_BACKTRACE, tid, timeout_secs); if (sock_fd < 0) { return -1; } @@ -127,7 +149,11 @@ int dump_backtrace_to_file(pid_t tid, int fd) { } int dump_tombstone(pid_t tid, char* pathbuf, size_t pathlen) { - int sock_fd = make_dump_request(DEBUGGER_ACTION_DUMP_TOMBSTONE, tid); + return dump_tombstone_timeout(tid, pathbuf, pathlen, 0); +} + +int dump_tombstone_timeout(pid_t tid, char* pathbuf, size_t pathlen, int timeout_secs) { + int sock_fd = make_dump_request(DEBUGGER_ACTION_DUMP_TOMBSTONE, tid, timeout_secs); if (sock_fd < 0) { return -1; }