diff options
author | Christopher Ferris <cferris@google.com> | 2016-05-05 17:55:41 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2016-05-05 17:55:41 +0000 |
commit | e423c24f74aaf0cb5d73a228d92ec4e4a56b0f4f (patch) | |
tree | 17621c9241f8a557aefee89e27a76b10d90d50b8 /debuggerd/debuggerd.cpp | |
parent | 6993211d38547d7007a87cbcd006f0f19c598ff9 (diff) | |
parent | a7431cfa570c6385ecd2041d56ead2603d7b7b80 (diff) | |
download | system_core-e423c24f74aaf0cb5d73a228d92ec4e4a56b0f4f.tar.gz system_core-e423c24f74aaf0cb5d73a228d92ec4e4a56b0f4f.tar.bz2 system_core-e423c24f74aaf0cb5d73a228d92ec4e4a56b0f4f.zip |
Merge "Fix problem with wait_for_gdb." into nyc-dev
am: a7431cfa57
* commit 'a7431cfa570c6385ecd2041d56ead2603d7b7b80':
Fix problem with wait_for_gdb.
Change-Id: I6d995c423f4ad9134965a215b1eea4cc7fd338b9
Diffstat (limited to 'debuggerd/debuggerd.cpp')
-rw-r--r-- | debuggerd/debuggerd.cpp | 65 |
1 files changed, 58 insertions, 7 deletions
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp index 0a43622c5..d2e6c2971 100644 --- a/debuggerd/debuggerd.cpp +++ b/debuggerd/debuggerd.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include <arpa/inet.h> #include <dirent.h> #include <elf.h> #include <errno.h> @@ -32,12 +33,15 @@ #include <sys/un.h> #include <time.h> +#include <memory> #include <set> +#include <string> #include <selinux/android.h> #include <log/logger.h> +#include <android-base/file.h> #include <android-base/unique_fd.h> #include <cutils/debugger.h> #include <cutils/properties.h> @@ -287,6 +291,41 @@ static int activity_manager_connect() { return amfd.release(); } +static void activity_manager_write(int pid, int signal, int amfd, const std::string& amfd_data) { + if (amfd == -1) { + return; + } + + // Activity Manager protocol: binary 32-bit network-byte-order ints for the + // pid and signal number, followed by the raw text of the dump, culminating + // in a zero byte that marks end-of-data. + uint32_t datum = htonl(pid); + if (!android::base::WriteFully(amfd, &datum, 4)) { + ALOGE("AM pid write failed: %s\n", strerror(errno)); + return; + } + datum = htonl(signal); + if (!android::base::WriteFully(amfd, &datum, 4)) { + ALOGE("AM signal write failed: %s\n", strerror(errno)); + return; + } + + if (!android::base::WriteFully(amfd, amfd_data.c_str(), amfd_data.size())) { + ALOGE("AM data write failed: %s\n", strerror(errno)); + return; + } + + // Send EOD to the Activity Manager, then wait for its ack to avoid racing + // ahead and killing the target out from under it. + uint8_t eodMarker = 0; + if (!android::base::WriteFully(amfd, &eodMarker, 1)) { + ALOGE("AM eod write failed: %s\n", strerror(errno)); + return; + } + // 3 sec timeout reading the ack; we're fine if the read fails. + android::base::ReadFully(amfd, &eodMarker, 1); +} + static bool should_attach_gdb(const debugger_request_t& request) { if (request.action == DEBUGGER_ACTION_CRASH) { return property_get_bool("debug.debuggerd.wait_for_gdb", false); @@ -414,7 +453,7 @@ static void ptrace_siblings(pid_t pid, pid_t main_tid, std::set<pid_t>& tids) { static bool perform_dump(const debugger_request_t& request, int fd, int tombstone_fd, BacktraceMap* backtrace_map, const std::set<pid_t>& siblings, - int* crash_signal, int amfd) { + int* crash_signal, std::string* amfd_data) { if (TEMP_FAILURE_RETRY(write(fd, "\0", 1)) != 1) { ALOGE("debuggerd: failed to respond to client: %s\n", strerror(errno)); return false; @@ -432,10 +471,10 @@ static bool perform_dump(const debugger_request_t& request, int fd, int tombston if (request.action == DEBUGGER_ACTION_DUMP_TOMBSTONE) { ALOGV("debuggerd: stopped -- dumping to tombstone"); engrave_tombstone(tombstone_fd, backtrace_map, request.pid, request.tid, siblings, signal, - request.original_si_code, request.abort_msg_address, amfd); + request.original_si_code, request.abort_msg_address, amfd_data); } else if (request.action == DEBUGGER_ACTION_DUMP_BACKTRACE) { ALOGV("debuggerd: stopped -- dumping to fd"); - dump_backtrace(fd, -1, backtrace_map, request.pid, request.tid, siblings); + dump_backtrace(fd, backtrace_map, request.pid, request.tid, siblings, nullptr); } else { ALOGV("debuggerd: stopped -- continuing"); if (ptrace(PTRACE_CONT, request.tid, 0, 0) != 0) { @@ -459,7 +498,7 @@ static bool perform_dump(const debugger_request_t& request, int fd, int tombston ALOGV("stopped -- fatal signal\n"); *crash_signal = signal; engrave_tombstone(tombstone_fd, backtrace_map, request.pid, request.tid, siblings, signal, - request.original_si_code, request.abort_msg_address, amfd); + request.original_si_code, request.abort_msg_address, amfd_data); break; default: @@ -546,9 +585,11 @@ static void worker_process(int fd, debugger_request_t& request) { std::unique_ptr<BacktraceMap> backtrace_map(BacktraceMap::Create(request.pid)); int amfd = -1; + std::unique_ptr<std::string> amfd_data; if (request.action == DEBUGGER_ACTION_CRASH) { // Connect to the activity manager before dropping privileges. amfd = activity_manager_connect(); + amfd_data.reset(new std::string); } bool succeeded = false; @@ -561,11 +602,11 @@ static void worker_process(int fd, debugger_request_t& request) { int crash_signal = SIGKILL; succeeded = perform_dump(request, fd, tombstone_fd, backtrace_map.get(), siblings, - &crash_signal, amfd); + &crash_signal, amfd_data.get()); if (succeeded) { if (request.action == DEBUGGER_ACTION_DUMP_TOMBSTONE) { if (!tombstone_path.empty()) { - write(fd, tombstone_path.c_str(), tombstone_path.length()); + android::base::WriteFully(fd, tombstone_path.c_str(), tombstone_path.length()); } } } @@ -578,6 +619,13 @@ static void worker_process(int fd, debugger_request_t& request) { } } + if (!attach_gdb) { + // Tell the Activity Manager about the crashing process. If we are + // waiting for gdb to attach, do not send this or Activity Manager + // might kill the process before anyone can attach. + activity_manager_write(request.pid, crash_signal, amfd, *amfd_data.get()); + } + if (ptrace(PTRACE_DETACH, request.tid, 0, 0) != 0) { ALOGE("debuggerd: ptrace detach from %d failed: %s", request.tid, strerror(errno)); } @@ -594,9 +642,12 @@ static void worker_process(int fd, debugger_request_t& request) { } // Wait for gdb, if requested. - if (attach_gdb && succeeded) { + if (attach_gdb) { wait_for_user_action(request); + // Now tell the activity manager about this process. + activity_manager_write(request.pid, crash_signal, amfd, *amfd_data.get()); + // Tell the signal process to send SIGCONT to the target. if (!send_signal(request.pid, 0, SIGCONT)) { ALOGE("debuggerd: failed to resume process %d: %s", request.pid, strerror(errno)); |