aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Mayer <fmayer@google.com>2018-05-18 10:43:14 +0100
committerFlorian Mayer <fmayer@google.com>2018-05-18 14:12:53 +0100
commit870dd82f0a1190b1890ca3e592f68bc5bbece627 (patch)
treee8e7da00d1b12f7770f3ef727670af02e259a742
parent361f1e2e39054b2002ce0b22b7c74387559610a8 (diff)
downloadperfetto-870dd82f0a1190b1890ca3e592f68bc5bbece627.tar.gz
Correctly handle EINTR.
This fixes a bug that made the CPU reader loop exit when the program gets send SIGSTOP. Cherry pick of http://aosp/689181. Bug: 79969427 Merged-In: I09ae42adb5b211e0eae73364dcef1b4d33762ed8 Change-Id: I0f76ba9d3aba77a607175fc1f31ec7edcfa2afe6
-rw-r--r--src/ftrace_reader/cpu_reader.cc16
-rw-r--r--src/ftrace_reader/cpu_reader.h5
2 files changed, 13 insertions, 8 deletions
diff --git a/src/ftrace_reader/cpu_reader.cc b/src/ftrace_reader/cpu_reader.cc
index 39e0fb5a2..c9e86d233 100644
--- a/src/ftrace_reader/cpu_reader.cc
+++ b/src/ftrace_reader/cpu_reader.cc
@@ -145,7 +145,7 @@ CpuReader::CpuReader(const ProtoTranslationTable* table,
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 @@ CpuReader::~CpuReader() {
// 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 @@ void CpuReader::RunWorkerThread(
// 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 ab2b3401e..7e6146339 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 @@ class CpuReader {
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 @@ class CpuReader {
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_)
};