Snap for 4793185 from 870dd82f0a1190b1890ca3e592f68bc5bbece627 to pi-release

Change-Id: Ibcdba8b3fd1d0eca84cddf8af93af50da2a24e0f
diff --git a/src/ftrace_reader/cpu_reader.cc b/src/ftrace_reader/cpu_reader.cc
index 39e0fb5..c9e86d2 100644
--- a/src/ftrace_reader/cpu_reader.cc
+++ b/src/ftrace_reader/cpu_reader.cc
@@ -145,7 +145,7 @@
 
   worker_thread_ =
       std::thread(std::bind(&RunWorkerThread, cpu_, *trace_fd_,
-                            *staging_write_fd_, on_data_available));
+                            *staging_write_fd_, on_data_available, &exiting_));
 }
 
 CpuReader::~CpuReader() {
@@ -155,17 +155,18 @@
   // trace fd (which prevents another splice from starting), raise SIGPIPE and
   // wait for the worker to exit (i.e., to guarantee no splice is in progress)
   // and only then close the staging pipe.
+  exiting_ = true;
   trace_fd_.reset();
   pthread_kill(worker_thread_.native_handle(), SIGPIPE);
   worker_thread_.join();
 }
 
 // static
-void CpuReader::RunWorkerThread(
-    size_t cpu,
-    int trace_fd,
-    int staging_write_fd,
-    const std::function<void()>& on_data_available) {
+void CpuReader::RunWorkerThread(size_t cpu,
+                                int trace_fd,
+                                int staging_write_fd,
+                                const std::function<void()>& on_data_available,
+                                std::atomic<bool>* exiting) {
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
   // This thread is responsible for moving data from the trace pipe into the
@@ -188,11 +189,12 @@
       // The kernel ftrace code has its own splice() implementation that can
       // occasionally fail with transient errors not reported in man 2 splice.
       // Just try again if we see these.
-      if (errno == ENOMEM || errno == EBUSY) {
+      if (errno == ENOMEM || errno == EBUSY || (errno == EINTR && !*exiting)) {
         PERFETTO_DPLOG("Transient splice failure -- retrying");
         usleep(100 * 1000);
         continue;
       }
+      PERFETTO_DPLOG("Stopping CPUReader loop for CPU %zd.", cpu);
       PERFETTO_DCHECK(errno == EPIPE || errno == EINTR || errno == EBADF);
       break;  // ~CpuReader is waiting to join this thread.
     }
diff --git a/src/ftrace_reader/cpu_reader.h b/src/ftrace_reader/cpu_reader.h
index ab2b340..7e61463 100644
--- a/src/ftrace_reader/cpu_reader.h
+++ b/src/ftrace_reader/cpu_reader.h
@@ -21,6 +21,7 @@
 #include <string.h>
 
 #include <array>
+#include <atomic>
 #include <memory>
 #include <set>
 #include <thread>
@@ -201,7 +202,8 @@
   static void RunWorkerThread(size_t cpu,
                               int trace_fd,
                               int staging_write_fd,
-                              const std::function<void()>& on_data_available);
+                              const std::function<void()>& on_data_available,
+                              std::atomic<bool>* exiting);
 
   uint8_t* GetBuffer();
   CpuReader(const CpuReader&) = delete;
@@ -214,6 +216,7 @@
   base::ScopedFile staging_write_fd_;
   std::unique_ptr<uint8_t[]> buffer_;
   std::thread worker_thread_;
+  std::atomic<bool> exiting_{false};
   PERFETTO_THREAD_CHECKER(thread_checker_)
 };