Snap for 7316203 from 351f0440f1362d6a74a7623dabd6cdc7c40833dc to rvc-platform-release

Change-Id: Idfbc20b5e7ff487d61ad1fc8ca2fe48b8b3e7056
diff --git a/src/perfetto_cmd/perfetto_cmd_android.cc b/src/perfetto_cmd/perfetto_cmd_android.cc
index f332073..1c82239 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 @@
 
   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