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