diff options
Diffstat (limited to 'debuggerd')
-rw-r--r-- | debuggerd/tombstoned/tombstoned.cpp | 31 |
1 files changed, 22 insertions, 9 deletions
diff --git a/debuggerd/tombstoned/tombstoned.cpp b/debuggerd/tombstoned/tombstoned.cpp index 2f16eb249..15ae40624 100644 --- a/debuggerd/tombstoned/tombstoned.cpp +++ b/debuggerd/tombstoned/tombstoned.cpp | |||
@@ -61,6 +61,7 @@ enum CrashStatus { | |||
61 | struct Crash { | 61 | struct 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,6 +354,8 @@ 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 && errno != ENOENT) { | 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; |
@@ -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 | ||
375 | fail: | 388 | fail: |