blob: 2b74fd4897288e74112540654f5b36fa063ace00 [file] [log] [blame]
Josh Gaocbe70cb2016-10-18 18:17:52 -07001/*
2 * Copyright 2016, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <fcntl.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <sys/stat.h>
21#include <sys/types.h>
22#include <unistd.h>
23
24#include <array>
25#include <deque>
Josh Gaocb68a032017-06-02 13:02:10 -070026#include <string>
Josh Gaocbe70cb2016-10-18 18:17:52 -070027#include <unordered_map>
Josh Gaocb68a032017-06-02 13:02:10 -070028#include <utility>
Josh Gaocbe70cb2016-10-18 18:17:52 -070029
30#include <event2/event.h>
31#include <event2/listener.h>
32#include <event2/thread.h>
33
Josh Gao5f87bbd2019-01-09 17:01:49 -080034#include <android-base/cmsg.h>
Josh Gaocbe70cb2016-10-18 18:17:52 -070035#include <android-base/logging.h>
Elliott Hughes35bb6d22017-06-26 13:54:05 -070036#include <android-base/properties.h>
Josh Gaocbe70cb2016-10-18 18:17:52 -070037#include <android-base/stringprintf.h>
38#include <android-base/unique_fd.h>
39#include <cutils/sockets.h>
40
Josh Gao55f79a52017-03-06 12:24:07 -080041#include "debuggerd/handler.h"
Narayan Kamatha73df602017-05-24 15:07:25 +010042#include "dump_type.h"
Narayan Kamath2d377cd2017-05-10 10:58:59 +010043#include "protocol.h"
44#include "util.h"
Josh Gaocbe70cb2016-10-18 18:17:52 -070045
46#include "intercept_manager.h"
47
Elliott Hughes35bb6d22017-06-26 13:54:05 -070048using android::base::GetIntProperty;
Josh Gao5f87bbd2019-01-09 17:01:49 -080049using android::base::SendFileDescriptors;
Josh Gaocbe70cb2016-10-18 18:17:52 -070050using android::base::StringPrintf;
Josh Gao9a61f682020-12-01 21:04:09 -080051
52using android::base::borrowed_fd;
Josh Gaocbe70cb2016-10-18 18:17:52 -070053using android::base::unique_fd;
54
55static InterceptManager* intercept_manager;
56
57enum CrashStatus {
58 kCrashStatusRunning,
59 kCrashStatusQueued,
60};
61
Josh Gaoe2aa6212020-11-18 15:56:36 -080062struct CrashArtifact {
63 unique_fd fd;
64 std::optional<std::string> temporary_path;
65};
66
67struct CrashArtifactPaths {
68 std::string text;
69};
70
71struct CrashOutput {
72 CrashArtifact text;
73};
74
Elliott Hughes35bb6d22017-06-26 13:54:05 -070075// Ownership of Crash is a bit messy.
76// It's either owned by an active event that must have a timeout, or owned by
77// queued_requests, in the case that multiple crashes come in at the same time.
78struct Crash {
79 ~Crash() { event_free(crash_event); }
80
Josh Gaoe2aa6212020-11-18 15:56:36 -080081 CrashOutput output;
Josh Gao48383c82018-04-18 18:11:01 -070082 unique_fd crash_socket_fd;
Elliott Hughes35bb6d22017-06-26 13:54:05 -070083 pid_t crash_pid;
84 event* crash_event = nullptr;
Elliott Hughes35bb6d22017-06-26 13:54:05 -070085
86 DebuggerdDumpType crash_type;
87};
Narayan Kamath922f6b22017-05-15 15:59:30 +010088
Narayan Kamatha73df602017-05-24 15:07:25 +010089class CrashQueue {
Narayan Kamath922f6b22017-05-15 15:59:30 +010090 public:
Narayan Kamatha73df602017-05-24 15:07:25 +010091 CrashQueue(const std::string& dir_path, const std::string& file_name_prefix, size_t max_artifacts,
Jerome Gaillard5ec54d12021-01-26 12:36:12 +000092 size_t max_concurrent_dumps)
Narayan Kamath922f6b22017-05-15 15:59:30 +010093 : file_name_prefix_(file_name_prefix),
94 dir_path_(dir_path),
95 dir_fd_(open(dir_path.c_str(), O_DIRECTORY | O_RDONLY | O_CLOEXEC)),
96 max_artifacts_(max_artifacts),
97 next_artifact_(0),
98 max_concurrent_dumps_(max_concurrent_dumps),
Jerome Gaillard5ec54d12021-01-26 12:36:12 +000099 num_concurrent_dumps_(0) {
Narayan Kamath922f6b22017-05-15 15:59:30 +0100100 if (dir_fd_ == -1) {
101 PLOG(FATAL) << "failed to open directory: " << dir_path;
102 }
103
104 // NOTE: If max_artifacts_ <= max_concurrent_dumps_, then theoretically the
105 // same filename could be handed out to multiple processes.
106 CHECK(max_artifacts_ > max_concurrent_dumps_);
107
108 find_oldest_artifact();
109 }
110
Elliott Hughes35bb6d22017-06-26 13:54:05 -0700111 static CrashQueue* for_crash(const Crash* crash) {
112 return (crash->crash_type == kDebuggerdJavaBacktrace) ? for_anrs() : for_tombstones();
113 }
114
Josh Gao9a61f682020-12-01 21:04:09 -0800115 static CrashQueue* for_crash(const std::unique_ptr<Crash>& crash) {
116 return for_crash(crash.get());
117 }
118
Elliott Hughes35bb6d22017-06-26 13:54:05 -0700119 static CrashQueue* for_tombstones() {
120 static CrashQueue queue("/data/tombstones", "tombstone_" /* file_name_prefix */,
Elliott Hughesec220cd2019-09-26 14:35:24 -0700121 GetIntProperty("tombstoned.max_tombstone_count", 32),
Jerome Gaillard5ec54d12021-01-26 12:36:12 +0000122 1 /* max_concurrent_dumps */);
Elliott Hughes35bb6d22017-06-26 13:54:05 -0700123 return &queue;
124 }
125
126 static CrashQueue* for_anrs() {
127 static CrashQueue queue("/data/anr", "trace_" /* file_name_prefix */,
128 GetIntProperty("tombstoned.max_anr_count", 64),
Jerome Gaillard5ec54d12021-01-26 12:36:12 +0000129 4 /* max_concurrent_dumps */);
Elliott Hughes35bb6d22017-06-26 13:54:05 -0700130 return &queue;
131 }
132
Josh Gaoe2aa6212020-11-18 15:56:36 -0800133 CrashArtifact create_temporary_file() const {
134 CrashArtifact result;
135
136 std::optional<std::string> path;
137 result.fd.reset(openat(dir_fd_, ".", O_WRONLY | O_APPEND | O_TMPFILE | O_CLOEXEC, 0640));
138 if (result.fd == -1) {
Josh Gaof5974ae2018-05-03 16:05:32 -0700139 // We might not have O_TMPFILE. Try creating with an arbitrary filename instead.
140 static size_t counter = 0;
141 std::string tmp_filename = StringPrintf(".temporary%zu", counter++);
Josh Gaoe2aa6212020-11-18 15:56:36 -0800142 result.fd.reset(openat(dir_fd_, tmp_filename.c_str(),
143 O_WRONLY | O_APPEND | O_CREAT | O_TRUNC | O_CLOEXEC, 0640));
144 if (result.fd == -1) {
Josh Gao48383c82018-04-18 18:11:01 -0700145 PLOG(FATAL) << "failed to create temporary tombstone in " << dir_path_;
146 }
Josh Gaof5974ae2018-05-03 16:05:32 -0700147
Josh Gaoe2aa6212020-11-18 15:56:36 -0800148 result.temporary_path = std::move(tmp_filename);
Narayan Kamath922f6b22017-05-15 15:59:30 +0100149 }
Josh Gaoe2aa6212020-11-18 15:56:36 -0800150
151 return std::move(result);
Josh Gao48383c82018-04-18 18:11:01 -0700152 }
Narayan Kamath922f6b22017-05-15 15:59:30 +0100153
Josh Gaoe2aa6212020-11-18 15:56:36 -0800154 std::optional<CrashOutput> get_output(DebuggerdDumpType dump_type) {
155 CrashOutput result;
156
157 switch (dump_type) {
158 case kDebuggerdNativeBacktrace:
159 case kDebuggerdJavaBacktrace:
160 // Don't generate tombstones for backtrace requests.
161 return {};
162
163 case kDebuggerdTombstone:
164 result.text = create_temporary_file();
165 break;
166
167 default:
168 LOG(ERROR) << "unexpected dump type: " << dump_type;
169 return {};
170 }
171
172 return result;
173 }
174
175 borrowed_fd dir_fd() { return dir_fd_; }
176
177 CrashArtifactPaths get_next_artifact_paths() {
178 CrashArtifactPaths result;
179 result.text = StringPrintf("%s%02d", file_name_prefix_.c_str(), next_artifact_);
180
Narayan Kamath922f6b22017-05-15 15:59:30 +0100181 next_artifact_ = (next_artifact_ + 1) % max_artifacts_;
Josh Gaoe2aa6212020-11-18 15:56:36 -0800182 return result;
Narayan Kamath922f6b22017-05-15 15:59:30 +0100183 }
184
Josh Gao9a61f682020-12-01 21:04:09 -0800185 // Consumes crash if it returns true, otherwise leaves it untouched.
186 bool maybe_enqueue_crash(std::unique_ptr<Crash>&& crash) {
Narayan Kamath922f6b22017-05-15 15:59:30 +0100187 if (num_concurrent_dumps_ == max_concurrent_dumps_) {
Josh Gao9a61f682020-12-01 21:04:09 -0800188 queued_requests_.emplace_back(std::move(crash));
Narayan Kamath922f6b22017-05-15 15:59:30 +0100189 return true;
190 }
191
192 return false;
193 }
194
Josh Gao9a61f682020-12-01 21:04:09 -0800195 void maybe_dequeue_crashes(void (*handler)(std::unique_ptr<Crash> crash)) {
Narayan Kamath922f6b22017-05-15 15:59:30 +0100196 while (!queued_requests_.empty() && num_concurrent_dumps_ < max_concurrent_dumps_) {
Josh Gao9a61f682020-12-01 21:04:09 -0800197 std::unique_ptr<Crash> next_crash = std::move(queued_requests_.front());
Narayan Kamath922f6b22017-05-15 15:59:30 +0100198 queued_requests_.pop_front();
Josh Gao9a61f682020-12-01 21:04:09 -0800199 handler(std::move(next_crash));
Narayan Kamath922f6b22017-05-15 15:59:30 +0100200 }
201 }
202
203 void on_crash_started() { ++num_concurrent_dumps_; }
204
205 void on_crash_completed() { --num_concurrent_dumps_; }
206
Narayan Kamath922f6b22017-05-15 15:59:30 +0100207 private:
208 void find_oldest_artifact() {
209 size_t oldest_tombstone = 0;
210 time_t oldest_time = std::numeric_limits<time_t>::max();
211
212 for (size_t i = 0; i < max_artifacts_; ++i) {
Josh Gaoe2aa6212020-11-18 15:56:36 -0800213 std::string path =
214 StringPrintf("%s/%s%02zu", dir_path_.c_str(), file_name_prefix_.c_str(), i);
Narayan Kamath922f6b22017-05-15 15:59:30 +0100215 struct stat st;
216 if (stat(path.c_str(), &st) != 0) {
217 if (errno == ENOENT) {
218 oldest_tombstone = i;
219 break;
220 } else {
221 PLOG(ERROR) << "failed to stat " << path;
222 continue;
223 }
224 }
225
226 if (st.st_mtime < oldest_time) {
227 oldest_tombstone = i;
228 oldest_time = st.st_mtime;
229 }
230 }
231
232 next_artifact_ = oldest_tombstone;
233 }
234
235 const std::string file_name_prefix_;
236
237 const std::string dir_path_;
238 const int dir_fd_;
239
240 const size_t max_artifacts_;
241 int next_artifact_;
242
243 const size_t max_concurrent_dumps_;
244 size_t num_concurrent_dumps_;
245
Josh Gao9a61f682020-12-01 21:04:09 -0800246 std::deque<std::unique_ptr<Crash>> queued_requests_;
Narayan Kamath922f6b22017-05-15 15:59:30 +0100247
Narayan Kamatha73df602017-05-24 15:07:25 +0100248 DISALLOW_COPY_AND_ASSIGN(CrashQueue);
Narayan Kamath922f6b22017-05-15 15:59:30 +0100249};
250
251// Whether java trace dumps are produced via tombstoned.
Narayan Kamathca5e9082017-06-02 15:42:06 +0100252static constexpr bool kJavaTraceDumpsEnabled = true;
Narayan Kamath922f6b22017-05-15 15:59:30 +0100253
Josh Gaocbe70cb2016-10-18 18:17:52 -0700254// Forward declare the callbacks so they can be placed in a sensible order.
Josh Gaoe2aa6212020-11-18 15:56:36 -0800255static void crash_accept_cb(evconnlistener* listener, evutil_socket_t sockfd, sockaddr*, int,
256 void*);
Josh Gaocbe70cb2016-10-18 18:17:52 -0700257static void crash_request_cb(evutil_socket_t sockfd, short ev, void* arg);
258static void crash_completed_cb(evutil_socket_t sockfd, short ev, void* arg);
259
Josh Gao9a61f682020-12-01 21:04:09 -0800260static void perform_request(std::unique_ptr<Crash> crash) {
Josh Gaocbe70cb2016-10-18 18:17:52 -0700261 unique_fd output_fd;
Josh Gao48383c82018-04-18 18:11:01 -0700262 bool intercepted =
263 intercept_manager->GetIntercept(crash->crash_pid, crash->crash_type, &output_fd);
Jerome Gaillard5ec54d12021-01-26 12:36:12 +0000264 if (!intercepted) {
Josh Gaoe2aa6212020-11-18 15:56:36 -0800265 if (auto o = CrashQueue::for_crash(crash.get())->get_output(crash->crash_type); o) {
266 crash->output = std::move(*o);
267 output_fd.reset(dup(crash->output.text.fd));
Josh Gao2b22ae12018-09-12 14:51:03 -0700268 } else {
Josh Gaoe2aa6212020-11-18 15:56:36 -0800269 LOG(ERROR) << "failed to get crash output for type " << crash->crash_type;
270 return;
Josh Gao2b22ae12018-09-12 14:51:03 -0700271 }
Josh Gaocbe70cb2016-10-18 18:17:52 -0700272 }
273
Josh Gaoe2aa6212020-11-18 15:56:36 -0800274 TombstonedCrashPacket response = {.packet_type = CrashPacketType::kPerformDump};
275
Jerome Gaillard5ec54d12021-01-26 12:36:12 +0000276 ssize_t rc =
277 SendFileDescriptors(crash->crash_socket_fd, &response, sizeof(response), output_fd.get());
Josh Gaoe2aa6212020-11-18 15:56:36 -0800278
Josh Gao5f87bbd2019-01-09 17:01:49 -0800279 output_fd.reset();
280
Josh Gaocbe70cb2016-10-18 18:17:52 -0700281 if (rc == -1) {
282 PLOG(WARNING) << "failed to send response to CrashRequest";
Josh Gao9a61f682020-12-01 21:04:09 -0800283 return;
Josh Gaocbe70cb2016-10-18 18:17:52 -0700284 } else if (rc != sizeof(response)) {
285 PLOG(WARNING) << "crash socket write returned short";
Josh Gao9a61f682020-12-01 21:04:09 -0800286 return;
Josh Gaocbe70cb2016-10-18 18:17:52 -0700287 }
Josh Gao13078242017-03-30 14:42:46 -0700288
Josh Gao9a61f682020-12-01 21:04:09 -0800289 // TODO: Make this configurable by the interceptor?
290 struct timeval timeout = {10, 0};
Josh Gaocbe70cb2016-10-18 18:17:52 -0700291
Josh Gao9a61f682020-12-01 21:04:09 -0800292 event_base* base = event_get_base(crash->crash_event);
293
294 event_assign(crash->crash_event, base, crash->crash_socket_fd, EV_TIMEOUT | EV_READ,
295 crash_completed_cb, crash.get());
296 event_add(crash->crash_event, &timeout);
297 CrashQueue::for_crash(crash)->on_crash_started();
298
299 // The crash is now owned by the event loop.
300 crash.release();
Josh Gaocbe70cb2016-10-18 18:17:52 -0700301}
302
303static void crash_accept_cb(evconnlistener* listener, evutil_socket_t sockfd, sockaddr*, int,
Narayan Kamatha73df602017-05-24 15:07:25 +0100304 void*) {
Josh Gaocbe70cb2016-10-18 18:17:52 -0700305 event_base* base = evconnlistener_get_base(listener);
306 Crash* crash = new Crash();
307
Narayan Kamatha73df602017-05-24 15:07:25 +0100308 // TODO: Make sure that only java crashes come in on the java socket
309 // and only native crashes on the native socket.
Josh Gaocbe70cb2016-10-18 18:17:52 -0700310 struct timeval timeout = { 1, 0 };
311 event* crash_event = event_new(base, sockfd, EV_TIMEOUT | EV_READ, crash_request_cb, crash);
Josh Gao48383c82018-04-18 18:11:01 -0700312 crash->crash_socket_fd.reset(sockfd);
Josh Gaocbe70cb2016-10-18 18:17:52 -0700313 crash->crash_event = crash_event;
314 event_add(crash_event, &timeout);
315}
316
317static void crash_request_cb(evutil_socket_t sockfd, short ev, void* arg) {
Josh Gao9a61f682020-12-01 21:04:09 -0800318 std::unique_ptr<Crash> crash(static_cast<Crash*>(arg));
Josh Gaocbe70cb2016-10-18 18:17:52 -0700319 TombstonedCrashPacket request = {};
320
321 if ((ev & EV_TIMEOUT) != 0) {
322 LOG(WARNING) << "crash request timed out";
Josh Gao9a61f682020-12-01 21:04:09 -0800323 return;
Josh Gaocbe70cb2016-10-18 18:17:52 -0700324 } else if ((ev & EV_READ) == 0) {
325 LOG(WARNING) << "tombstoned received unexpected event from crash socket";
Josh Gao9a61f682020-12-01 21:04:09 -0800326 return;
Josh Gaocbe70cb2016-10-18 18:17:52 -0700327 }
328
Josh Gao9a61f682020-12-01 21:04:09 -0800329 ssize_t rc = TEMP_FAILURE_RETRY(read(sockfd, &request, sizeof(request)));
Josh Gaocbe70cb2016-10-18 18:17:52 -0700330 if (rc == -1) {
331 PLOG(WARNING) << "failed to read from crash socket";
Josh Gao9a61f682020-12-01 21:04:09 -0800332 return;
Josh Gaocbe70cb2016-10-18 18:17:52 -0700333 } else if (rc != sizeof(request)) {
334 LOG(WARNING) << "crash socket received short read of length " << rc << " (expected "
335 << sizeof(request) << ")";
Josh Gao9a61f682020-12-01 21:04:09 -0800336 return;
Josh Gaocbe70cb2016-10-18 18:17:52 -0700337 }
338
339 if (request.packet_type != CrashPacketType::kDumpRequest) {
340 LOG(WARNING) << "unexpected crash packet type, expected kDumpRequest, received "
341 << StringPrintf("%#2hhX", request.packet_type);
Josh Gao9a61f682020-12-01 21:04:09 -0800342 return;
Josh Gaocbe70cb2016-10-18 18:17:52 -0700343 }
344
Narayan Kamatha73df602017-05-24 15:07:25 +0100345 crash->crash_type = request.packet.dump_request.dump_type;
Jerome Gaillard5ec54d12021-01-26 12:36:12 +0000346 if (crash->crash_type < 0 || crash->crash_type > kDebuggerdAnyIntercept) {
Narayan Kamatha73df602017-05-24 15:07:25 +0100347 LOG(WARNING) << "unexpected crash dump type: " << crash->crash_type;
Josh Gao9a61f682020-12-01 21:04:09 -0800348 return;
Narayan Kamatha73df602017-05-24 15:07:25 +0100349 }
350
351 if (crash->crash_type != kDebuggerdJavaBacktrace) {
Narayan Kamath922f6b22017-05-15 15:59:30 +0100352 crash->crash_pid = request.packet.dump_request.pid;
353 } else {
354 // Requests for java traces are sent from untrusted processes, so we
355 // must not trust the PID sent down with the request. Instead, we ask the
356 // kernel.
357 ucred cr = {};
358 socklen_t len = sizeof(cr);
359 int ret = getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &cr, &len);
360 if (ret != 0) {
361 PLOG(ERROR) << "Failed to getsockopt(..SO_PEERCRED)";
Josh Gao9a61f682020-12-01 21:04:09 -0800362 return;
Narayan Kamath922f6b22017-05-15 15:59:30 +0100363 }
364
365 crash->crash_pid = cr.pid;
366 }
367
Josh Gao9a61f682020-12-01 21:04:09 -0800368 pid_t crash_pid = crash->crash_pid;
369 LOG(INFO) << "received crash request for pid " << crash_pid;
Josh Gaocbe70cb2016-10-18 18:17:52 -0700370
Josh Gao9a61f682020-12-01 21:04:09 -0800371 if (CrashQueue::for_crash(crash)->maybe_enqueue_crash(std::move(crash))) {
372 LOG(INFO) << "enqueueing crash request for pid " << crash_pid;
Josh Gaocbe70cb2016-10-18 18:17:52 -0700373 } else {
Josh Gao9a61f682020-12-01 21:04:09 -0800374 perform_request(std::move(crash));
Josh Gaocbe70cb2016-10-18 18:17:52 -0700375 }
Josh Gaocbe70cb2016-10-18 18:17:52 -0700376}
377
Josh Gaoe2aa6212020-11-18 15:56:36 -0800378static bool link_fd(borrowed_fd fd, borrowed_fd dirfd, const std::string& path) {
379 std::string fd_path = StringPrintf("/proc/self/fd/%d", fd.get());
380
381 int rc = linkat(AT_FDCWD, fd_path.c_str(), dirfd.get(), path.c_str(), AT_SYMLINK_FOLLOW);
382 if (rc != 0) {
383 PLOG(ERROR) << "failed to link file descriptor";
384 return false;
385 }
386 return true;
387}
388
Josh Gao9a61f682020-12-01 21:04:09 -0800389static void crash_completed(borrowed_fd sockfd, std::unique_ptr<Crash> crash) {
Josh Gaocbe70cb2016-10-18 18:17:52 -0700390 TombstonedCrashPacket request = {};
Josh Gaoe2aa6212020-11-18 15:56:36 -0800391 CrashQueue* queue = CrashQueue::for_crash(crash);
Josh Gaocbe70cb2016-10-18 18:17:52 -0700392
Josh Gao9a61f682020-12-01 21:04:09 -0800393 ssize_t rc = TEMP_FAILURE_RETRY(read(sockfd.get(), &request, sizeof(request)));
Josh Gaocbe70cb2016-10-18 18:17:52 -0700394 if (rc == -1) {
395 PLOG(WARNING) << "failed to read from crash socket";
Josh Gao9a61f682020-12-01 21:04:09 -0800396 return;
Josh Gaocbe70cb2016-10-18 18:17:52 -0700397 } else if (rc != sizeof(request)) {
398 LOG(WARNING) << "crash socket received short read of length " << rc << " (expected "
399 << sizeof(request) << ")";
Josh Gao9a61f682020-12-01 21:04:09 -0800400 return;
Josh Gaocbe70cb2016-10-18 18:17:52 -0700401 }
402
403 if (request.packet_type != CrashPacketType::kCompletedDump) {
404 LOG(WARNING) << "unexpected crash packet type, expected kCompletedDump, received "
405 << uint32_t(request.packet_type);
Josh Gao9a61f682020-12-01 21:04:09 -0800406 return;
Josh Gaocbe70cb2016-10-18 18:17:52 -0700407 }
408
Josh Gaoe2aa6212020-11-18 15:56:36 -0800409 if (crash->output.text.fd == -1) {
410 LOG(WARNING) << "missing output fd";
411 return;
412 }
Josh Gaof5974ae2018-05-03 16:05:32 -0700413
Josh Gaoe2aa6212020-11-18 15:56:36 -0800414 CrashArtifactPaths paths = queue->get_next_artifact_paths();
Josh Gao48383c82018-04-18 18:11:01 -0700415
Josh Gaoe2aa6212020-11-18 15:56:36 -0800416 // Always try to unlink the tombstone file.
417 // linkat doesn't let us replace a file, so we need to unlink before linking
418 // our results onto disk, and if we fail for some reason, we should delete
419 // stale tombstones to avoid confusing inconsistency.
420 rc = unlinkat(queue->dir_fd().get(), paths.text.c_str(), 0);
421 if (rc != 0 && errno != ENOENT) {
422 PLOG(ERROR) << "failed to unlink tombstone at " << paths.text;
423 return;
424 }
425
426 if (crash->output.text.fd != -1) {
427 if (!link_fd(crash->output.text.fd, queue->dir_fd(), paths.text)) {
428 LOG(ERROR) << "failed to link tombstone";
Narayan Kamath79dd1432017-06-21 19:42:00 +0100429 } else {
Josh Gao48383c82018-04-18 18:11:01 -0700430 if (crash->crash_type == kDebuggerdJavaBacktrace) {
Josh Gaoe2aa6212020-11-18 15:56:36 -0800431 LOG(ERROR) << "Traces for pid " << crash->crash_pid << " written to: " << paths.text;
Josh Gao48383c82018-04-18 18:11:01 -0700432 } else {
433 // NOTE: Several tools parse this log message to figure out where the
434 // tombstone associated with a given native crash was written. Any changes
435 // to this message must be carefully considered.
Josh Gaoe2aa6212020-11-18 15:56:36 -0800436 LOG(ERROR) << "Tombstone written to: " << paths.text;
Josh Gao48383c82018-04-18 18:11:01 -0700437 }
Narayan Kamath79dd1432017-06-21 19:42:00 +0100438 }
Josh Gaoe2aa6212020-11-18 15:56:36 -0800439 }
Josh Gaof5974ae2018-05-03 16:05:32 -0700440
Josh Gaoe2aa6212020-11-18 15:56:36 -0800441 // If we don't have O_TMPFILE, we need to clean up after ourselves.
442 if (crash->output.text.temporary_path) {
443 rc = unlinkat(queue->dir_fd().get(), crash->output.text.temporary_path->c_str(), 0);
444 if (rc != 0) {
445 PLOG(ERROR) << "failed to unlink temporary tombstone at " << paths.text;
Josh Gaof5974ae2018-05-03 16:05:32 -0700446 }
Josh Gaocb68a032017-06-02 13:02:10 -0700447 }
Josh Gao9a61f682020-12-01 21:04:09 -0800448}
Josh Gaocb68a032017-06-02 13:02:10 -0700449
Josh Gao9a61f682020-12-01 21:04:09 -0800450static void crash_completed_cb(evutil_socket_t sockfd, short ev, void* arg) {
451 std::unique_ptr<Crash> crash(static_cast<Crash*>(arg));
Elliott Hughes35bb6d22017-06-26 13:54:05 -0700452 CrashQueue* queue = CrashQueue::for_crash(crash);
Josh Gao9a61f682020-12-01 21:04:09 -0800453
Josh Gaoe2aa6212020-11-18 15:56:36 -0800454 queue->on_crash_completed();
Josh Gao9a61f682020-12-01 21:04:09 -0800455
456 if ((ev & EV_READ) == EV_READ) {
457 crash_completed(sockfd, std::move(crash));
458 }
Josh Gaocbe70cb2016-10-18 18:17:52 -0700459
460 // If there's something queued up, let them proceed.
Narayan Kamatha73df602017-05-24 15:07:25 +0100461 queue->maybe_dequeue_crashes(perform_request);
Josh Gaocbe70cb2016-10-18 18:17:52 -0700462}
463
464int main(int, char* []) {
Josh Gao8830c952017-03-06 12:23:55 -0800465 umask(0137);
466
Josh Gao55f79a52017-03-06 12:24:07 -0800467 // Don't try to connect to ourselves if we crash.
468 struct sigaction action = {};
469 action.sa_handler = [](int signal) {
470 LOG(ERROR) << "received fatal signal " << signal;
471 _exit(1);
472 };
473 debuggerd_register_handlers(&action);
474
Josh Gaocbe70cb2016-10-18 18:17:52 -0700475 int intercept_socket = android_get_control_socket(kTombstonedInterceptSocketName);
476 int crash_socket = android_get_control_socket(kTombstonedCrashSocketName);
477
478 if (intercept_socket == -1 || crash_socket == -1) {
479 PLOG(FATAL) << "failed to get socket from init";
480 }
481
482 evutil_make_socket_nonblocking(intercept_socket);
483 evutil_make_socket_nonblocking(crash_socket);
484
485 event_base* base = event_base_new();
486 if (!base) {
487 LOG(FATAL) << "failed to create event_base";
488 }
489
490 intercept_manager = new InterceptManager(base, intercept_socket);
491
Narayan Kamathc2e98f62017-09-13 13:12:34 +0100492 evconnlistener* tombstone_listener =
493 evconnlistener_new(base, crash_accept_cb, CrashQueue::for_tombstones(), LEV_OPT_CLOSE_ON_FREE,
494 -1 /* backlog */, crash_socket);
Narayan Kamath922f6b22017-05-15 15:59:30 +0100495 if (!tombstone_listener) {
496 LOG(FATAL) << "failed to create evconnlistener for tombstones.";
497 }
498
499 if (kJavaTraceDumpsEnabled) {
500 const int java_trace_socket = android_get_control_socket(kTombstonedJavaTraceSocketName);
501 if (java_trace_socket == -1) {
502 PLOG(FATAL) << "failed to get socket from init";
503 }
504
505 evutil_make_socket_nonblocking(java_trace_socket);
Narayan Kamathc2e98f62017-09-13 13:12:34 +0100506 evconnlistener* java_trace_listener =
507 evconnlistener_new(base, crash_accept_cb, CrashQueue::for_anrs(), LEV_OPT_CLOSE_ON_FREE,
508 -1 /* backlog */, java_trace_socket);
Narayan Kamath922f6b22017-05-15 15:59:30 +0100509 if (!java_trace_listener) {
510 LOG(FATAL) << "failed to create evconnlistener for java traces.";
511 }
Josh Gaocbe70cb2016-10-18 18:17:52 -0700512 }
513
514 LOG(INFO) << "tombstoned successfully initialized";
515 event_base_dispatch(base);
516}