Merge "perfetto: bump sqlite version"
diff --git a/BUILD.gn b/BUILD.gn
index f5a0eb1..ca8a9c3 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -66,6 +66,7 @@
"tools/ftrace_proto_gen:ftrace_proto_gen",
"tools/proto_to_cpp",
"tools/trace_to_text",
+ "tools/trace_to_text:trace_to_text_lite_host($host_toolchain)",
]
if (is_linux || is_android) {
deps += [ "tools/skippy" ]
diff --git a/protos/third_party/pprof/profile.proto b/protos/third_party/pprof/profile.proto
index 9540940..2c4acca 100644
--- a/protos/third_party/pprof/profile.proto
+++ b/protos/third_party/pprof/profile.proto
@@ -43,6 +43,11 @@
option java_package = "com.google.perftools.profiles";
option java_outer_classname = "ProfileProto";
+// Perfetto Changes ===========================================================
+// 1. Add optimize_for = LITE_RUNTIME
+option optimize_for = LITE_RUNTIME;
+// ============================================================================
+
message Profile {
// A description of the samples associated with each Sample.value.
// For a cpu profile this might be:
diff --git a/src/traced/probes/filesystem/inode_file_data_source.cc b/src/traced/probes/filesystem/inode_file_data_source.cc
index 9d3a098..02eed04 100644
--- a/src/traced/probes/filesystem/inode_file_data_source.cc
+++ b/src/traced/probes/filesystem/inode_file_data_source.cc
@@ -182,9 +182,10 @@
PERFETTO_DLOG("%" PRIu64 " inodes found in cache", cache_found_count);
}
-void InodeFileDataSource::Flush() {
+void InodeFileDataSource::Flush(FlushRequestID,
+ std::function<void()> callback) {
ResetTracePacket();
- writer_->Flush();
+ writer_->Flush(callback);
}
void InodeFileDataSource::OnInodes(
diff --git a/src/traced/probes/filesystem/inode_file_data_source.h b/src/traced/probes/filesystem/inode_file_data_source.h
index 143df66..2afdeed 100644
--- a/src/traced/probes/filesystem/inode_file_data_source.h
+++ b/src/traced/probes/filesystem/inode_file_data_source.h
@@ -85,7 +85,7 @@
// ProbesDataSource implementation.
void Start() override;
- void Flush() override;
+ void Flush(FlushRequestID, std::function<void()> callback) override;
protected:
std::multimap<BlockDeviceID, std::string> mount_points_;
diff --git a/src/traced/probes/ftrace/atrace_wrapper.cc b/src/traced/probes/ftrace/atrace_wrapper.cc
index 5987d46..3132c66 100644
--- a/src/traced/probes/ftrace/atrace_wrapper.cc
+++ b/src/traced/probes/ftrace/atrace_wrapper.cc
@@ -17,6 +17,7 @@
#include "src/traced/probes/ftrace/atrace_wrapper.h"
#include <fcntl.h>
+#include <poll.h>
#include <stdint.h>
#include <string.h>
#include <sys/stat.h>
@@ -25,6 +26,7 @@
#include <unistd.h>
#include "perfetto/base/logging.h"
+#include "perfetto/base/time.h"
namespace perfetto {
@@ -46,8 +48,10 @@
// Create the pipe for the child process to return stderr.
int filedes[2];
- if (pipe(filedes) == -1)
- return false;
+ PERFETTO_CHECK(pipe(filedes) == 0);
+
+ int err = fcntl(filedes[0], F_SETFL, fcntl(filedes[0], F_GETFL) | O_NONBLOCK);
+ PERFETTO_CHECK(err == 0);
pid_t pid = fork();
PERFETTO_CHECK(pid >= 0);
@@ -55,7 +59,7 @@
// Duplicate the write end of the pipe into stderr.
if ((dup2(filedes[1], STDERR_FILENO) == -1)) {
const char kError[] = "Unable to duplicate stderr fd";
- write(filedes[1], kError, sizeof(kError));
+ base::ignore_result(write(filedes[1], kError, sizeof(kError)));
_exit(1);
}
@@ -79,14 +83,62 @@
close(filedes[1]);
// Collect the output from child process.
- std::string error;
char buffer[4096];
- while (true) {
- ssize_t count = PERFETTO_EINTR(read(filedes[0], buffer, sizeof(buffer)));
- if (count == 0 || count == -1)
+ std::string error;
+
+ // Get the read end of the pipe.
+ constexpr uint8_t kFdCount = 1;
+ struct pollfd fds[kFdCount]{};
+ fds[0].fd = filedes[0];
+ fds[0].events = POLLIN;
+
+ // Store the start time of atrace and setup the timeout.
+ constexpr auto timeout = base::TimeMillis(7500);
+ auto start = base::GetWallTimeMs();
+ for (;;) {
+ // Check if we are below the timeout and update the select timeout to
+ // the time remaining.
+ auto now = base::GetWallTimeMs();
+ auto remaining = timeout - (now - start);
+ auto timeout_ms = static_cast<int>(remaining.count());
+ if (timeout_ms <= 0) {
+ // Kill atrace.
+ kill(pid, SIGKILL);
+
+ std::string cmdline = "/system/bin/atrace";
+ for (const auto& arg : args) {
+ cmdline += " " + arg;
+ }
+ error.append("Timed out waiting for atrace (cmdline: " + cmdline + ")");
break;
+ }
+
+ // Wait for the value of the timeout.
+ auto ret = poll(fds, kFdCount, timeout_ms);
+ if (ret == 0 || (ret < 0 && errno == EINTR)) {
+ // Either timeout occured in poll (in which case continue so that this
+ // will be picked up by our own timeout logic) or we received an EINTR and
+ // we should try again.
+ continue;
+ } else if (ret < 0) {
+ error.append("Error while polling atrace stderr");
+ break;
+ }
+
+ // Data is available to be read from the fd.
+ int64_t count = PERFETTO_EINTR(read(filedes[0], buffer, sizeof(buffer)));
+ if (ret < 0 && errno == EAGAIN) {
+ continue;
+ } else if (count < 0) {
+ error.append("Error while reading atrace stderr");
+ break;
+ } else if (count == 0) {
+ // EOF so we can exit this loop.
+ break;
+ }
error.append(buffer, static_cast<size_t>(count));
}
+
// Close the read end of the pipe.
close(filedes[0]);
@@ -96,7 +148,7 @@
bool ok = WIFEXITED(status) && WEXITSTATUS(status) == 0;
if (!ok) {
// TODO(lalitm): use the stderr result from atrace.
- base::ignore_result(error);
+ PERFETTO_ELOG("%s", error.c_str());
}
return ok;
}
diff --git a/src/traced/probes/ftrace/ftrace_data_source.cc b/src/traced/probes/ftrace/ftrace_data_source.cc
index d7bc843..0272cd4 100644
--- a/src/traced/probes/ftrace/ftrace_data_source.cc
+++ b/src/traced/probes/ftrace/ftrace_data_source.cc
@@ -65,7 +65,7 @@
controller_weak_->DumpFtraceStats(stats);
}
-void FtraceDataSource::Flush() {
+void FtraceDataSource::Flush(FlushRequestID, std::function<void()> callback) {
// TODO(primiano): this still doesn't flush data from the kernel ftrace
// buffers (see b/73886018). We should do that and delay the
// NotifyFlushComplete() until the ftrace data has been drained from the
@@ -73,7 +73,7 @@
if (!writer_)
return;
WriteStats();
- writer_->Flush();
+ writer_->Flush(callback);
}
void FtraceDataSource::WriteStats() {
diff --git a/src/traced/probes/ftrace/ftrace_data_source.h b/src/traced/probes/ftrace/ftrace_data_source.h
index e576a5a..f15c1d1 100644
--- a/src/traced/probes/ftrace/ftrace_data_source.h
+++ b/src/traced/probes/ftrace/ftrace_data_source.h
@@ -67,7 +67,7 @@
// Flushes the ftrace buffers into the userspace trace buffers and writes
// also ftrace stats.
- void Flush() override;
+ void Flush(FlushRequestID, std::function<void()> callback) override;
FtraceConfigId config_id() const { return config_id_; }
const FtraceConfig& config() const { return config_; }
diff --git a/src/traced/probes/probes_data_source.h b/src/traced/probes/probes_data_source.h
index 13d47e1..1e0e8cb 100644
--- a/src/traced/probes/probes_data_source.h
+++ b/src/traced/probes/probes_data_source.h
@@ -17,6 +17,8 @@
#ifndef SRC_TRACED_PROBES_PROBES_DATA_SOURCE_H_
#define SRC_TRACED_PROBES_PROBES_DATA_SOURCE_H_
+#include <functional>
+
#include "perfetto/tracing/core/basic_types.h"
namespace perfetto {
@@ -29,7 +31,7 @@
virtual ~ProbesDataSource();
virtual void Start() = 0;
- virtual void Flush() = 0;
+ virtual void Flush(FlushRequestID, std::function<void()> callback) = 0;
const TracingSessionID tracing_session_id;
const int type_id;
diff --git a/src/traced/probes/probes_producer.cc b/src/traced/probes/probes_producer.cc
index c309180..b7d666c 100644
--- a/src/traced/probes/probes_producer.cc
+++ b/src/traced/probes/probes_producer.cc
@@ -47,6 +47,10 @@
constexpr uint32_t kInitialConnectionBackoffMs = 100;
constexpr uint32_t kMaxConnectionBackoffMs = 30 * 1000;
+
+// Should be larger than FtraceController::kFlushTimeoutMs.
+constexpr uint32_t kFlushTimeoutMs = 1000;
+
constexpr char kFtraceSourceName[] = "linux.ftrace";
constexpr char kProcessStatsSourceName[] = "linux.process_stats";
constexpr char kInodeMapSourceName[] = "linux.inode_file_map";
@@ -280,12 +284,64 @@
void ProbesProducer::Flush(FlushRequestID flush_request_id,
const DataSourceInstanceID* data_source_ids,
size_t num_data_sources) {
+ PERFETTO_DCHECK(flush_request_id);
+ auto weak_this = weak_factory_.GetWeakPtr();
+
+ // Issue a Flush() to all started data sources.
+ bool flush_queued = false;
for (size_t i = 0; i < num_data_sources; i++) {
- auto it = data_sources_.find(data_source_ids[i]);
+ DataSourceInstanceID ds_id = data_source_ids[i];
+ auto it = data_sources_.find(ds_id);
if (it == data_sources_.end() || !it->second->started)
continue;
- it->second->Flush();
+ pending_flushes_.emplace(flush_request_id, ds_id);
+ flush_queued = true;
+ auto flush_callback = [weak_this, flush_request_id, ds_id] {
+ if (weak_this)
+ weak_this->OnDataSourceFlushComplete(flush_request_id, ds_id);
+ };
+ it->second->Flush(flush_request_id, flush_callback);
}
+
+ // If there is nothing to flush, ack immediately.
+ if (!flush_queued) {
+ endpoint_->NotifyFlushComplete(flush_request_id);
+ return;
+ }
+
+ // Otherwise, post the timeout task.
+ task_runner_->PostDelayedTask(
+ [weak_this, flush_request_id] {
+ if (weak_this)
+ weak_this->OnFlushTimeout(flush_request_id);
+ },
+ kFlushTimeoutMs);
+}
+
+void ProbesProducer::OnDataSourceFlushComplete(FlushRequestID flush_request_id,
+ DataSourceInstanceID ds_id) {
+ PERFETTO_DLOG("Flush %" PRIu64 " acked by data source %" PRIu64,
+ flush_request_id, ds_id);
+ auto range = pending_flushes_.equal_range(flush_request_id);
+ for (auto it = range.first; it != range.second; it++) {
+ if (it->second == ds_id) {
+ pending_flushes_.erase(it);
+ break;
+ }
+ }
+
+ if (pending_flushes_.count(flush_request_id))
+ return; // Still waiting for other data sources to ack.
+
+ PERFETTO_DLOG("All data sources acked to flush %" PRIu64, flush_request_id);
+ endpoint_->NotifyFlushComplete(flush_request_id);
+}
+
+void ProbesProducer::OnFlushTimeout(FlushRequestID flush_request_id) {
+ if (pending_flushes_.count(flush_request_id) == 0)
+ return; // All acked.
+ PERFETTO_ELOG("Flush(%" PRIu64 ") timed out", flush_request_id);
+ pending_flushes_.erase(flush_request_id);
endpoint_->NotifyFlushComplete(flush_request_id);
}
diff --git a/src/traced/probes/probes_producer.h b/src/traced/probes/probes_producer.h
index 14737d6..44ac19e 100644
--- a/src/traced/probes/probes_producer.h
+++ b/src/traced/probes/probes_producer.h
@@ -95,6 +95,8 @@
void Restart();
void ResetConnectionBackoff();
void IncreaseConnectionBackoff();
+ void OnDataSourceFlushComplete(FlushRequestID, DataSourceInstanceID);
+ void OnFlushTimeout(FlushRequestID);
State state_ = kNotStarted;
base::TaskRunner* task_runner_ = nullptr;
@@ -112,6 +114,9 @@
std::unordered_multimap<TracingSessionID, ProbesDataSource*>
session_data_sources_;
+ std::unordered_multimap<FlushRequestID, DataSourceInstanceID>
+ pending_flushes_;
+
std::unordered_map<DataSourceInstanceID, base::Watchdog::Timer> watchdogs_;
LRUInodeCache cache_{kLRUInodeCacheSize};
std::map<BlockDeviceID, std::unordered_map<Inode, InodeMapValue>>
diff --git a/src/traced/probes/ps/process_stats_data_source.cc b/src/traced/probes/ps/process_stats_data_source.cc
index ddff880..858f25f 100644
--- a/src/traced/probes/ps/process_stats_data_source.cc
+++ b/src/traced/probes/ps/process_stats_data_source.cc
@@ -161,11 +161,12 @@
FinalizeCurPacket();
}
-void ProcessStatsDataSource::Flush() {
+void ProcessStatsDataSource::Flush(FlushRequestID,
+ std::function<void()> callback) {
// We shouldn't get this in the middle of WriteAllProcesses() or OnPids().
PERFETTO_DCHECK(!cur_ps_tree_);
PERFETTO_DCHECK(!cur_ps_stats_);
- writer_->Flush();
+ writer_->Flush(callback);
}
void ProcessStatsDataSource::WriteProcessOrThread(int32_t pid) {
diff --git a/src/traced/probes/ps/process_stats_data_source.h b/src/traced/probes/ps/process_stats_data_source.h
index 65b6e2e..f5329cf 100644
--- a/src/traced/probes/ps/process_stats_data_source.h
+++ b/src/traced/probes/ps/process_stats_data_source.h
@@ -57,7 +57,7 @@
// ProbesDataSource implementation.
void Start() override;
- void Flush() override;
+ void Flush(FlushRequestID, std::function<void()> callback) override;
bool on_demand_dumps_enabled() const { return enable_on_demand_dumps_; }
diff --git a/src/traced/probes/ps/process_stats_data_source_unittest.cc b/src/traced/probes/ps/process_stats_data_source_unittest.cc
index 4587cda..b985bcc 100644
--- a/src/traced/probes/ps/process_stats_data_source_unittest.cc
+++ b/src/traced/probes/ps/process_stats_data_source_unittest.cc
@@ -169,7 +169,7 @@
data_source->Start();
task_runner_.RunUntilCheckpoint("all_done");
- data_source->Flush();
+ data_source->Flush(1 /* FlushRequestId */, []() {});
// |packet| will contain the merge of all kNumIter packets written.
std::unique_ptr<protos::TracePacket> packet = writer_raw_->ParseProto();
diff --git a/src/traced/probes/sys_stats/sys_stats_data_source.cc b/src/traced/probes/sys_stats/sys_stats_data_source.cc
index 61d869d..befe396 100644
--- a/src/traced/probes/sys_stats/sys_stats_data_source.cc
+++ b/src/traced/probes/sys_stats/sys_stats_data_source.cc
@@ -297,8 +297,8 @@
return weak_factory_.GetWeakPtr();
}
-void SysStatsDataSource::Flush() {
- writer_->Flush();
+void SysStatsDataSource::Flush(FlushRequestID, std::function<void()> callback) {
+ writer_->Flush(callback);
}
size_t SysStatsDataSource::ReadFile(base::ScopedFile* fd, const char* path) {
diff --git a/src/traced/probes/sys_stats/sys_stats_data_source.h b/src/traced/probes/sys_stats/sys_stats_data_source.h
index bdb5e10..0fa085c 100644
--- a/src/traced/probes/sys_stats/sys_stats_data_source.h
+++ b/src/traced/probes/sys_stats/sys_stats_data_source.h
@@ -56,7 +56,7 @@
// ProbesDataSource implementation.
void Start() override;
- void Flush() override;
+ void Flush(FlushRequestID, std::function<void()> callback) override;
base::WeakPtr<SysStatsDataSource> GetWeakPtr() const;
diff --git a/src/tracing/core/trace_writer_impl.cc b/src/tracing/core/trace_writer_impl.cc
index bfdf1f4..0d0e3e2 100644
--- a/src/tracing/core/trace_writer_impl.cc
+++ b/src/tracing/core/trace_writer_impl.cc
@@ -68,10 +68,12 @@
if (cur_chunk_.is_valid()) {
shmem_arbiter_->ReturnCompletedChunk(std::move(cur_chunk_), target_buffer_,
&patch_list_);
- shmem_arbiter_->FlushPendingCommitDataRequests(callback);
} else {
PERFETTO_DCHECK(patch_list_.empty());
}
+ // Always issue the Flush request, even if there is nothing to flush, just
+ // for the sake of getting the callback posted back.
+ shmem_arbiter_->FlushPendingCommitDataRequests(callback);
protobuf_stream_writer_.Reset({nullptr, nullptr});
}
diff --git a/tools/trace_to_text/BUILD.gn b/tools/trace_to_text/BUILD.gn
index 019b244..97ada9c 100644
--- a/tools/trace_to_text/BUILD.gn
+++ b/tools/trace_to_text/BUILD.gn
@@ -80,6 +80,15 @@
"../../gn:default_deps",
]
}
+
+ # WASM is too permissive, build a normal version of the binary to test for
+ # missing symbols.
+ executable("trace_to_text_lite_host") {
+ deps = [
+ ":lite",
+ "../../gn:default_deps",
+ ]
+ }
}
wasm_lib("trace_to_text_wasm") {
diff --git a/tools/trace_to_text/trace_to_profile.cc b/tools/trace_to_text/trace_to_profile.cc
index 9849090..4ddb9b7 100644
--- a/tools/trace_to_text/trace_to_profile.cc
+++ b/tools/trace_to_text/trace_to_profile.cc
@@ -20,6 +20,7 @@
#include <algorithm>
#include <map>
+#include <set>
#include <vector>
#include "tools/trace_to_text/utils.h"