summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'debuggerd')
-rw-r--r--debuggerd/tombstoned/tombstoned.cpp33
1 files changed, 23 insertions, 10 deletions
diff --git a/debuggerd/tombstoned/tombstoned.cpp b/debuggerd/tombstoned/tombstoned.cpp
index 5dffa5b3c..15ae40624 100644
--- a/debuggerd/tombstoned/tombstoned.cpp
+++ b/debuggerd/tombstoned/tombstoned.cpp
@@ -61,6 +61,7 @@ enum CrashStatus {
61struct Crash { 61struct Crash {
62 ~Crash() { event_free(crash_event); } 62 ~Crash() { event_free(crash_event); }
63 63
64 std::string crash_tombstone_path;
64 unique_fd crash_tombstone_fd; 65 unique_fd crash_tombstone_fd;
65 unique_fd crash_socket_fd; 66 unique_fd crash_socket_fd;
66 pid_t crash_pid; 67 pid_t crash_pid;
@@ -109,20 +110,22 @@ class CrashQueue {
109 return &queue; 110 return &queue;
110 } 111 }
111 112
112 unique_fd get_output() { 113 std::pair<std::string, unique_fd> get_output() {
114 std::string path;
113 unique_fd result(openat(dir_fd_, ".", O_WRONLY | O_APPEND | O_TMPFILE | O_CLOEXEC, 0640)); 115 unique_fd result(openat(dir_fd_, ".", O_WRONLY | O_APPEND | O_TMPFILE | O_CLOEXEC, 0640));
114 if (result == -1) { 116 if (result == -1) {
115 // We might not have O_TMPFILE. Try creating and unlinking instead. 117 // We might not have O_TMPFILE. Try creating with an arbitrary filename instead.
116 result.reset( 118 static size_t counter = 0;
117 openat(dir_fd_, ".temporary", O_WRONLY | O_APPEND | O_CREAT | O_TRUNC | O_CLOEXEC, 0640)); 119 std::string tmp_filename = StringPrintf(".temporary%zu", counter++);
120 result.reset(openat(dir_fd_, tmp_filename.c_str(),
121 O_WRONLY | O_APPEND | O_CREAT | O_TRUNC | O_CLOEXEC, 0640));
118 if (result == -1) { 122 if (result == -1) {
119 PLOG(FATAL) << "failed to create temporary tombstone in " << dir_path_; 123 PLOG(FATAL) << "failed to create temporary tombstone in " << dir_path_;
120 } 124 }
121 if (unlinkat(dir_fd_, ".temporary", 0) != 0) { 125
122 PLOG(FATAL) << "failed to unlink temporary tombstone"; 126 path = StringPrintf("%s/%s", dir_path_.c_str(), tmp_filename.c_str());
123 }
124 } 127 }
125 return result; 128 return std::make_pair(std::move(path), std::move(result));
126 } 129 }
127 130
128 std::string get_next_artifact_path() { 131 std::string get_next_artifact_path() {
@@ -209,7 +212,7 @@ static void perform_request(Crash* crash) {
209 bool intercepted = 212 bool intercepted =
210 intercept_manager->GetIntercept(crash->crash_pid, crash->crash_type, &output_fd); 213 intercept_manager->GetIntercept(crash->crash_pid, crash->crash_type, &output_fd);
211 if (!intercepted) { 214 if (!intercepted) {
212 output_fd = CrashQueue::for_crash(crash)->get_output(); 215 std::tie(crash->crash_tombstone_path, output_fd) = CrashQueue::for_crash(crash)->get_output();
213 crash->crash_tombstone_fd.reset(dup(output_fd.get())); 216 crash->crash_tombstone_fd.reset(dup(output_fd.get()));
214 } 217 }
215 218
@@ -351,8 +354,10 @@ static void crash_completed_cb(evutil_socket_t sockfd, short ev, void* arg) {
351 if (crash->crash_tombstone_fd != -1) { 354 if (crash->crash_tombstone_fd != -1) {
352 std::string fd_path = StringPrintf("/proc/self/fd/%d", crash->crash_tombstone_fd.get()); 355 std::string fd_path = StringPrintf("/proc/self/fd/%d", crash->crash_tombstone_fd.get());
353 std::string tombstone_path = CrashQueue::for_crash(crash)->get_next_artifact_path(); 356 std::string tombstone_path = CrashQueue::for_crash(crash)->get_next_artifact_path();
357
358 // linkat doesn't let us replace a file, so we need to unlink first.
354 int rc = unlink(tombstone_path.c_str()); 359 int rc = unlink(tombstone_path.c_str());
355 if (rc != 0) { 360 if (rc != 0 && errno != ENOENT) {
356 PLOG(ERROR) << "failed to unlink tombstone at " << tombstone_path; 361 PLOG(ERROR) << "failed to unlink tombstone at " << tombstone_path;
357 goto fail; 362 goto fail;
358 } 363 }
@@ -370,6 +375,14 @@ static void crash_completed_cb(evutil_socket_t sockfd, short ev, void* arg) {
370 LOG(ERROR) << "Tombstone written to: " << tombstone_path; 375 LOG(ERROR) << "Tombstone written to: " << tombstone_path;
371 } 376 }
372 } 377 }
378
379 // If we don't have O_TMPFILE, we need to clean up after ourselves.
380 if (!crash->crash_tombstone_path.empty()) {
381 rc = unlink(crash->crash_tombstone_path.c_str());
382 if (rc != 0) {
383 PLOG(ERROR) << "failed to unlink temporary tombstone at " << crash->crash_tombstone_path;
384 }
385 }
373 } 386 }
374 387
375fail: 388fail: