tombstoned: make missing O_TMPFILE workaround actually work around.
We can't actually link an unlinked file back onto disk if it wasn't
opened with O_TMPFILE. Switch to using a temporary filename instead.
Bug: http://b/77729983
Test: agampe
Change-Id: I1970497114f0056065a1ba65f6358f08b51ec551
(cherry picked from commit f5974aedc4
)
This commit is contained in:
parent
5a9929a392
commit
e96dc1a061
1 changed files with 22 additions and 9 deletions
|
@ -61,6 +61,7 @@ enum CrashStatus {
|
|||
struct Crash {
|
||||
~Crash() { event_free(crash_event); }
|
||||
|
||||
std::string crash_tombstone_path;
|
||||
unique_fd crash_tombstone_fd;
|
||||
unique_fd crash_socket_fd;
|
||||
pid_t crash_pid;
|
||||
|
@ -109,20 +110,22 @@ class CrashQueue {
|
|||
return &queue;
|
||||
}
|
||||
|
||||
unique_fd get_output() {
|
||||
std::pair<std::string, unique_fd> get_output() {
|
||||
std::string path;
|
||||
unique_fd result(openat(dir_fd_, ".", O_WRONLY | O_APPEND | O_TMPFILE | O_CLOEXEC, 0640));
|
||||
if (result == -1) {
|
||||
// We might not have O_TMPFILE. Try creating and unlinking instead.
|
||||
result.reset(
|
||||
openat(dir_fd_, ".temporary", O_WRONLY | O_APPEND | O_CREAT | O_TRUNC | O_CLOEXEC, 0640));
|
||||
// We might not have O_TMPFILE. Try creating with an arbitrary filename instead.
|
||||
static size_t counter = 0;
|
||||
std::string tmp_filename = StringPrintf(".temporary%zu", counter++);
|
||||
result.reset(openat(dir_fd_, tmp_filename.c_str(),
|
||||
O_WRONLY | O_APPEND | O_CREAT | O_TRUNC | O_CLOEXEC, 0640));
|
||||
if (result == -1) {
|
||||
PLOG(FATAL) << "failed to create temporary tombstone in " << dir_path_;
|
||||
}
|
||||
if (unlinkat(dir_fd_, ".temporary", 0) != 0) {
|
||||
PLOG(FATAL) << "failed to unlink temporary tombstone";
|
||||
}
|
||||
|
||||
path = StringPrintf("%s/%s", dir_path_.c_str(), tmp_filename.c_str());
|
||||
}
|
||||
return result;
|
||||
return std::make_pair(std::move(path), std::move(result));
|
||||
}
|
||||
|
||||
std::string get_next_artifact_path() {
|
||||
|
@ -209,7 +212,7 @@ static void perform_request(Crash* crash) {
|
|||
bool intercepted =
|
||||
intercept_manager->GetIntercept(crash->crash_pid, crash->crash_type, &output_fd);
|
||||
if (!intercepted) {
|
||||
output_fd = CrashQueue::for_crash(crash)->get_output();
|
||||
std::tie(crash->crash_tombstone_path, output_fd) = CrashQueue::for_crash(crash)->get_output();
|
||||
crash->crash_tombstone_fd.reset(dup(output_fd.get()));
|
||||
}
|
||||
|
||||
|
@ -351,6 +354,8 @@ static void crash_completed_cb(evutil_socket_t sockfd, short ev, void* arg) {
|
|||
if (crash->crash_tombstone_fd != -1) {
|
||||
std::string fd_path = StringPrintf("/proc/self/fd/%d", crash->crash_tombstone_fd.get());
|
||||
std::string tombstone_path = CrashQueue::for_crash(crash)->get_next_artifact_path();
|
||||
|
||||
// linkat doesn't let us replace a file, so we need to unlink first.
|
||||
int rc = unlink(tombstone_path.c_str());
|
||||
if (rc != 0 && errno != ENOENT) {
|
||||
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) {
|
|||
LOG(ERROR) << "Tombstone written to: " << tombstone_path;
|
||||
}
|
||||
}
|
||||
|
||||
// If we don't have O_TMPFILE, we need to clean up after ourselves.
|
||||
if (!crash->crash_tombstone_path.empty()) {
|
||||
rc = unlink(crash->crash_tombstone_path.c_str());
|
||||
if (rc != 0) {
|
||||
PLOG(ERROR) << "failed to unlink temporary tombstone at " << crash->crash_tombstone_path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
|
|
Loading…
Reference in a new issue