aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2021-05-04 17:50:47 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2021-05-04 17:50:47 +0000
commit4fc85f8ec7dd7d1fc4f74fc7d7f59c34ecad465e (patch)
tree7668518c925f25aff54bd420e283915dea3d2853
parent3e3173ed00bfc0f8a9bba50bce281c29f776e758 (diff)
parent351f0440f1362d6a74a7623dabd6cdc7c40833dc (diff)
downloadperfetto-android-platform-11.0.0_r20.tar.gz
Change-Id: Idfbc20b5e7ff487d61ad1fc8ca2fe48b8b3e7056
-rw-r--r--src/perfetto_cmd/perfetto_cmd_android.cc43
1 files changed, 39 insertions, 4 deletions
diff --git a/src/perfetto_cmd/perfetto_cmd_android.cc b/src/perfetto_cmd/perfetto_cmd_android.cc
index f33207399..1c82239a5 100644
--- a/src/perfetto_cmd/perfetto_cmd_android.cc
+++ b/src/perfetto_cmd/perfetto_cmd_android.cc
@@ -29,6 +29,11 @@
#include "src/android_internal/statsd_logging.h"
namespace perfetto {
+namespace {
+
+constexpr int64_t kSendfileTimeoutNs = 10UL * 1000 * 1000 * 1000; // 10s
+
+} // namespace
void PerfettoCmd::SaveTraceIntoDropboxAndIncidentOrCrash() {
PERFETTO_CHECK(!dropbox_tag_.empty());
@@ -107,14 +112,44 @@ void PerfettoCmd::SaveOutputToIncidentTraceOrCrash() {
PERFETTO_CHECK(unlink(kTempIncidentTracePath) == 0 || errno == ENOENT);
+ // TODO(b/155024256) These should not be necessary (we flush when destroying
+ // packet writer and sendfile should ignore file offset) however they should
+ // not harm anything and it will help debug the linked issue.
+ PERFETTO_CHECK(fflush(*trace_out_stream_) == 0);
+ PERFETTO_CHECK(fseek(*trace_out_stream_, 0, SEEK_SET) == 0);
+
// SELinux constrains the set of readers.
base::ScopedFile staging_fd =
- base::OpenFile(kTempIncidentTracePath, O_CREAT | O_RDWR, 0666);
+ base::OpenFile(kTempIncidentTracePath, O_CREAT | O_EXCL | O_RDWR, 0666);
PERFETTO_CHECK(staging_fd);
+
+ int fd = fileno(*trace_out_stream_);
off_t offset = 0;
- auto wsize = sendfile(*staging_fd, fileno(*trace_out_stream_), &offset,
- static_cast<size_t>(bytes_written_));
- PERFETTO_CHECK(wsize == static_cast<ssize_t>(bytes_written_));
+ size_t remaining = static_cast<size_t>(bytes_written_);
+
+ base::TimeNanos start = base::GetBootTimeNs();
+ for (;;) {
+ errno = 0;
+ PERFETTO_DCHECK(static_cast<size_t>(offset) + remaining == bytes_written_);
+ auto wsize = PERFETTO_EINTR(sendfile(*staging_fd, fd, &offset, remaining));
+ if (wsize < 0) {
+ PERFETTO_FATAL("sendfile() failed wsize=%zd, off=%" PRId64
+ ", initial=%" PRIu64 ", remaining=%zu",
+ wsize, static_cast<int64_t>(offset), bytes_written_,
+ remaining);
+ }
+ remaining -= static_cast<size_t>(wsize);
+ if (remaining == 0) {
+ break;
+ }
+ if ((base::GetBootTimeNs() - start).count() > kSendfileTimeoutNs) {
+ PERFETTO_FATAL("sendfile() timed out wsize=%zd, off=%" PRId64
+ ", initial=%" PRIu64 ", remaining=%zu",
+ wsize, static_cast<int64_t>(offset), bytes_written_,
+ remaining);
+ }
+ }
+
staging_fd.reset();
PERFETTO_CHECK(rename(kTempIncidentTracePath, kIncidentTracePath) == 0);
// Note: not calling fsync(2), as we're not interested in the file being