1e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao/* 2e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao * Copyright (C) 2017 The Android Open Source Project 3e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao * All rights reserved. 4e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao * 5e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao * Redistribution and use in source and binary forms, with or without 6e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao * modification, are permitted provided that the following conditions 7e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao * are met: 8e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao * * Redistributions of source code must retain the above copyright 9e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao * notice, this list of conditions and the following disclaimer. 10e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao * * Redistributions in binary form must reproduce the above copyright 11e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao * notice, this list of conditions and the following disclaimer in 12e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao * the documentation and/or other materials provided with the 13e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao * distribution. 14e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao * 15e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao * SUCH DAMAGE. 27e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao */ 28e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao 29e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao#include <dirent.h> 30e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao#include <fcntl.h> 31e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao#include <poll.h> 32e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao#include <pthread.h> 33e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao#include <stddef.h> 34e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao#include <sys/ucontext.h> 35e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao#include <syscall.h> 36e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao#include <unistd.h> 37e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao 38e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao#include <atomic> 39e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 40e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao#include <android-base/file.h> 41e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao#include <android-base/unique_fd.h> 42e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 43e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao#include "debuggerd/handler.h" 44e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao#include "debuggerd/tombstoned.h" 45e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao#include "debuggerd/util.h" 46e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 47e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao#include "backtrace.h" 48e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao#include "tombstone.h" 49e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao 50e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao#include "private/libc_logging.h" 51e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 52e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gaousing android::base::unique_fd; 53e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 54e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gaoextern "C" void __linker_enable_fallback_allocator(); 55e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gaoextern "C" void __linker_disable_fallback_allocator(); 56e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 57e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao// This is incredibly sketchy to do inside of a signal handler, especially when libbacktrace 58e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao// uses the C++ standard library throughout, but this code runs in the linker, so we'll be using 59e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao// the linker's malloc instead of the libc one. Switch it out for a replacement, just in case. 60e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao// 61e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao// This isn't the default method of dumping because it can fail in cases such as address space 62e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao// exhaustion. 63e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gaostatic void debuggerd_fallback_trace(int output_fd, ucontext_t* ucontext) { 64e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao __linker_enable_fallback_allocator(); 65e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao dump_backtrace_ucontext(output_fd, ucontext); 66e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao __linker_disable_fallback_allocator(); 67e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao} 68e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 69e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gaostatic void debuggerd_fallback_tombstone(int output_fd, ucontext_t* ucontext, siginfo_t* siginfo, 70e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao void* abort_message) { 71e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao __linker_enable_fallback_allocator(); 72e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao engrave_tombstone_ucontext(output_fd, reinterpret_cast<uintptr_t>(abort_message), siginfo, 73e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao ucontext); 74e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao __linker_disable_fallback_allocator(); 75e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao} 76e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 77e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gaostatic void iterate_siblings(bool (*callback)(pid_t, int), int output_fd) { 78e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao pid_t current_tid = gettid(); 79e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao char buf[BUFSIZ]; 80e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao snprintf(buf, sizeof(buf), "/proc/%d/task", current_tid); 81e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao DIR* dir = opendir(buf); 82e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 83e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao if (!dir) { 84e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao __libc_format_log(ANDROID_LOG_ERROR, "libc", "failed to open %s: %s", buf, strerror(errno)); 85e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao return; 86e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao } 87e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 88e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao struct dirent* ent; 89e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao while ((ent = readdir(dir))) { 90e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao char* end; 91e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao long tid = strtol(ent->d_name, &end, 10); 92e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao if (end == ent->d_name || *end != '\0') { 93e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao continue; 94e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao } 95e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 96e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao if (tid != current_tid) { 97e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao callback(tid, output_fd); 98e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao } 99e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao } 100e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao closedir(dir); 101e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao} 102e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 103e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gaostatic bool forward_output(int src_fd, int dst_fd) { 104e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao // Make sure the thread actually got the signal. 105e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao struct pollfd pfd = { 106e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao .fd = src_fd, .events = POLLIN, 107e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao }; 108e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 109e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao // Wait for up to a second for output to start flowing. 110e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao if (poll(&pfd, 1, 1000) != 1) { 111e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao return false; 112e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao } 113e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 114e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao while (true) { 115e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao char buf[512]; 116e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao ssize_t rc = TEMP_FAILURE_RETRY(read(src_fd, buf, sizeof(buf))); 117e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao if (rc == 0) { 118e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao return true; 119e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao } else if (rc < 0) { 120e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao return false; 121e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao } 122e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 123e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao if (!android::base::WriteFully(dst_fd, buf, rc)) { 124e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao // We failed to write to tombstoned, but there's not much we can do. 125e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao // Keep reading from src_fd to keep things going. 126e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao continue; 127e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao } 128e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao } 129e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao} 130e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 131e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gaostatic void trace_handler(siginfo_t* info, ucontext_t* ucontext) { 132e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao static std::atomic<int> trace_output_fd(-1); 133e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 134e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao if (info->si_value.sival_int == ~0) { 135e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao // Asked to dump by the original signal recipient. 136e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao debuggerd_fallback_trace(trace_output_fd, ucontext); 137e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 138e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao int tmp = trace_output_fd.load(); 139e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao trace_output_fd.store(-1); 140e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao close(tmp); 141e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao return; 142e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao } 143e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 144e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao // Only allow one thread to perform a trace at a time. 145e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao static pthread_mutex_t trace_mutex = PTHREAD_MUTEX_INITIALIZER; 146e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao int ret = pthread_mutex_trylock(&trace_mutex); 147e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao if (ret != 0) { 148e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao __libc_format_log(ANDROID_LOG_INFO, "libc", "pthread_mutex_try_lock failed: %s", strerror(ret)); 149e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao return; 150e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao } 151e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 152e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao // Fetch output fd from tombstoned. 153e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao unique_fd tombstone_socket, output_fd; 154e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao if (!tombstoned_connect(getpid(), &tombstone_socket, &output_fd)) { 155e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao goto exit; 156e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao } 157e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 158e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao dump_backtrace_header(output_fd.get()); 159e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 160e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao // Dump our own stack. 161e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao debuggerd_fallback_trace(output_fd.get(), ucontext); 162e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 163e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao // Send a signal to all of our siblings, asking them to dump their stack. 164e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao iterate_siblings( 165e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao [](pid_t tid, int output_fd) { 166e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao // Use a pipe, to be able to detect situations where the thread gracefully exits before 167e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao // receiving our signal. 168e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao unique_fd pipe_read, pipe_write; 169e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao if (!Pipe(&pipe_read, &pipe_write)) { 170e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao __libc_format_log(ANDROID_LOG_ERROR, "libc", "failed to create pipe: %s", strerror(errno)); 171e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao return false; 172e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao } 173e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 174e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao trace_output_fd.store(pipe_write.get()); 175e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 176e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao siginfo_t siginfo = {}; 177e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao siginfo.si_code = SI_QUEUE; 178e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao siginfo.si_value.sival_int = ~0; 179e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao siginfo.si_pid = getpid(); 180e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao siginfo.si_uid = getuid(); 181e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 182e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao if (syscall(__NR_rt_tgsigqueueinfo, getpid(), tid, DEBUGGER_SIGNAL, &siginfo) != 0) { 183e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao __libc_format_log(ANDROID_LOG_ERROR, "libc", "failed to send trace signal to %d: %s", tid, 184e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao strerror(errno)); 185e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao return false; 186e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao } 187e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 188e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao bool success = forward_output(pipe_read.get(), output_fd); 189e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao if (success) { 190e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao // The signaled thread has closed trace_output_fd already. 191e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao (void)pipe_write.release(); 192e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao } else { 193e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao trace_output_fd.store(-1); 194e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao } 195e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 196e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao return true; 197e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao }, 198e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao output_fd.get()); 199e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 200e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao dump_backtrace_footer(output_fd.get()); 201e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao tombstoned_notify_completion(tombstone_socket.get()); 202e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 203e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gaoexit: 204e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao pthread_mutex_unlock(&trace_mutex); 205e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao} 206e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 207e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gaostatic void crash_handler(siginfo_t* info, ucontext_t* ucontext, void* abort_message) { 208e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao // Only allow one thread to handle a crash. 209e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao static pthread_mutex_t crash_mutex = PTHREAD_MUTEX_INITIALIZER; 210e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao int ret = pthread_mutex_lock(&crash_mutex); 211e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao if (ret != 0) { 212e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao __libc_format_log(ANDROID_LOG_INFO, "libc", "pthread_mutex_lock failed: %s", strerror(ret)); 213e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao return; 214e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao } 215e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 216e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao unique_fd tombstone_socket, output_fd; 217e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao bool tombstoned_connected = tombstoned_connect(getpid(), &tombstone_socket, &output_fd); 218e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao debuggerd_fallback_tombstone(output_fd.get(), ucontext, info, abort_message); 219e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao if (tombstoned_connected) { 220e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao tombstoned_notify_completion(tombstone_socket.get()); 221e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao } 222e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao} 223e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao 224e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gaoextern "C" void debuggerd_fallback_handler(siginfo_t* info, ucontext_t* ucontext, 225e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao void* abort_message) { 226e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao if (info->si_signo == DEBUGGER_SIGNAL) { 227e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao return trace_handler(info, ucontext); 228e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao } else { 229e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao return crash_handler(info, ucontext, abort_message); 230e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao } 231e73c932373e59e4c0351cc7a8bd8cc5b8910d87eJosh Gao} 232