Merge "Add WatchDog class to kill process after a timeout."
diff --git a/.travis.yml b/.travis.yml
index 4c45652..b96bf0c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -60,7 +60,7 @@
dist: trusty
sudo: true
compiler: clang
- env: CFG=linux_trusty-clang-x86_64-asan GN_ARGS="is_debug=false is_asan=true use_libfuzzer=true"
+ env: CFG=linux_trusty-clang-x86_64-asan GN_ARGS="is_debug=false is_asan=true"
- os: linux
dist: trusty
sudo: false
@@ -148,7 +148,6 @@
- tools/ninja -C out/dist -j8 all
- |
TEST_TARGETS="
- perfetto_integrationtests
perfetto_unittests
perfetto_benchmarks
"
diff --git a/gn/standalone/libc++/libc++.gni b/gn/standalone/libc++/libc++.gni
index 3306590..a44af48 100644
--- a/gn/standalone/libc++/libc++.gni
+++ b/gn/standalone/libc++/libc++.gni
@@ -45,3 +45,8 @@
libcxx_prefix = "//buildtools/libcxx"
libcxxabi_prefix = "//buildtools/libcxxabi"
+
+# TODO(b/72681031): Remove once alignment problems with custom libcxx are
+# resolved.
+assert(!(is_asan && use_libfuzzer) || !use_custom_libcxx,
+ "cannot use libfuzzer and ASAN with custom libcxx")
diff --git a/src/traced/perfetto_cmd/perfetto_cmd.cc b/src/traced/perfetto_cmd/perfetto_cmd.cc
index f3c236f..074a891 100644
--- a/src/traced/perfetto_cmd/perfetto_cmd.cc
+++ b/src/traced/perfetto_cmd/perfetto_cmd.cc
@@ -279,15 +279,23 @@
fflush(*trace_out_stream_);
long bytes_written = ftell(*trace_out_stream_);
+
if (!dropbox_tag_.empty()) {
#if defined(PERFETTO_BUILD_WITH_ANDROID)
android::sp<android::os::DropBoxManager> dropbox =
new android::os::DropBoxManager();
fseek(*trace_out_stream_, 0, SEEK_SET);
// DropBox takes ownership of the file descriptor, so give it a duplicate.
- base::ScopedFile fd(dup(fileno(*trace_out_stream_)));
- android::binder::Status status = dropbox->addFile(
- android::String16(dropbox_tag_.c_str()), fd.release(), 0 /* flags */);
+ // Also we need to give it a read-only copy of the fd or will hit a SELinux
+ // violation (about system_server ending up with a writable FD to our dir).
+ char fdpath[64];
+ sprintf(fdpath, "/proc/self/fd/%d", fileno(*trace_out_stream_));
+ base::ScopedFile read_only_fd(open(fdpath, O_RDONLY));
+ PERFETTO_CHECK(read_only_fd);
+ trace_out_stream_.reset();
+ android::binder::Status status =
+ dropbox->addFile(android::String16(dropbox_tag_.c_str()),
+ read_only_fd.release(), 0 /* flags */);
if (!status.isOk()) {
PERFETTO_ELOG("DropBox upload failed: %s", status.toString8().c_str());
return;
@@ -296,12 +304,12 @@
dropbox_tag_.c_str());
#endif // defined(PERFETTO_BUILD_WITH_ANDROID)
} else {
+ trace_out_stream_.reset();
PERFETTO_CHECK(
rename(tmp_trace_out_path_.c_str(), trace_out_path_.c_str()) == 0);
PERFETTO_ILOG("Wrote %ld bytes into %s", bytes_written,
trace_out_path_.c_str());
}
- trace_out_stream_.reset();
did_process_full_trace_ = true;
}
diff --git a/src/tracing/core/service_impl.cc b/src/tracing/core/service_impl.cc
index ad24f22..3ec7644 100644
--- a/src/tracing/core/service_impl.cc
+++ b/src/tracing/core/service_impl.cc
@@ -38,8 +38,6 @@
namespace perfetto {
-// TODO(fmayer): add ThreadChecker everywhere.
-
using protozero::proto_utils::ParseVarInt;
namespace {
@@ -72,6 +70,7 @@
std::unique_ptr<Service::ProducerEndpoint> ServiceImpl::ConnectProducer(
Producer* producer,
size_t shared_buffer_size_hint_bytes) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
const ProducerID id = ++last_producer_id_;
PERFETTO_DLOG("Producer %" PRIu64 " connected", id);
size_t shm_size = std::min(shared_buffer_size_hint_bytes, kMaxShmSize);
@@ -91,6 +90,7 @@
}
void ServiceImpl::DisconnectProducer(ProducerID id) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
PERFETTO_DLOG("Producer %" PRIu64 " disconnected", id);
PERFETTO_DCHECK(producers_.count(id));
producers_.erase(id);
@@ -98,6 +98,7 @@
ServiceImpl::ProducerEndpointImpl* ServiceImpl::GetProducer(
ProducerID id) const {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
auto it = producers_.find(id);
if (it == producers_.end())
return nullptr;
@@ -106,6 +107,7 @@
std::unique_ptr<Service::ConsumerEndpoint> ServiceImpl::ConnectConsumer(
Consumer* consumer) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
PERFETTO_DLOG("Consumer %p connected", reinterpret_cast<void*>(consumer));
std::unique_ptr<ConsumerEndpointImpl> endpoint(
new ConsumerEndpointImpl(this, task_runner_, consumer));
@@ -116,6 +118,7 @@
}
void ServiceImpl::DisconnectConsumer(ConsumerEndpointImpl* consumer) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
PERFETTO_DLOG("Consumer %p disconnected", reinterpret_cast<void*>(consumer));
PERFETTO_DCHECK(consumers_.count(consumer));
@@ -128,6 +131,7 @@
void ServiceImpl::EnableTracing(ConsumerEndpointImpl* consumer,
const TraceConfig& cfg) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
PERFETTO_DLOG("Enabling tracing for consumer %p",
reinterpret_cast<void*>(consumer));
if (consumer->tracing_session_id_) {
@@ -242,6 +246,7 @@
// and then drain the buffers. The actual teardown of the TracingSession happens
// in FreeBuffers().
void ServiceImpl::DisableTracing(TracingSessionID tsid) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
TracingSession* tracing_session = GetTracingSession(tsid);
if (!tracing_session) {
// Can happen if the consumer calls this before EnableTracing() or after
@@ -266,6 +271,7 @@
void ServiceImpl::ReadBuffers(TracingSessionID tsid,
ConsumerEndpointImpl* consumer) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
PERFETTO_DLOG("Reading buffers for session %" PRIu64, tsid);
TracingSession* tracing_session = GetTracingSession(tsid);
if (!tracing_session) {
@@ -349,6 +355,7 @@
}
void ServiceImpl::FreeBuffers(TracingSessionID tsid) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
PERFETTO_DLOG("Freeing buffers for session %" PRIu64, tsid);
TracingSession* tracing_session = GetTracingSession(tsid);
if (!tracing_session) {
@@ -370,6 +377,7 @@
void ServiceImpl::RegisterDataSource(ProducerID producer_id,
DataSourceID ds_id,
const DataSourceDescriptor& desc) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
PERFETTO_DLOG("Producer %" PRIu64
" registered data source \"%s\", ID: %" PRIu64,
producer_id, desc.name().c_str(), ds_id);
@@ -404,6 +412,7 @@
const TraceConfig::DataSource& cfg_data_source,
ProducerEndpointImpl* producer,
TracingSession* tracing_session) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
// TODO(primiano): match against |producer_name_filter| and add tests
// for registration ordering (data sources vs consumers).
@@ -441,6 +450,7 @@
// TODO(fmayer): right now the page_size in the SMB and the trace_buffers_ can
// mismatch. Remove the ability to decide the page size on the Producer.
+ PERFETTO_DCHECK_THREAD(thread_checker_);
auto buf_iter = buffers_.find(target_buffer_id);
if (buf_iter == buffers_.end()) {
PERFETTO_DLOG("Could not find target buffer %u for producer %" PRIu64,
@@ -468,6 +478,7 @@
ServiceImpl::TracingSession* ServiceImpl::GetTracingSession(
TracingSessionID tsid) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
auto it = tsid ? tracing_sessions_.find(tsid) : tracing_sessions_.end();
if (it == tracing_sessions_.end())
return nullptr;
@@ -489,10 +500,12 @@
}
void ServiceImpl::ConsumerEndpointImpl::EnableTracing(const TraceConfig& cfg) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
service_->EnableTracing(this, cfg);
}
void ServiceImpl::ConsumerEndpointImpl::DisableTracing() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
if (tracing_session_id_) {
service_->DisableTracing(tracing_session_id_);
} else {
@@ -501,6 +514,7 @@
}
void ServiceImpl::ConsumerEndpointImpl::ReadBuffers() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
if (tracing_session_id_) {
service_->ReadBuffers(tracing_session_id_, this);
} else {
@@ -509,6 +523,7 @@
}
void ServiceImpl::ConsumerEndpointImpl::FreeBuffers() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
if (tracing_session_id_) {
service_->FreeBuffers(tracing_session_id_);
} else {
@@ -518,6 +533,7 @@
base::WeakPtr<ServiceImpl::ConsumerEndpointImpl>
ServiceImpl::ConsumerEndpointImpl::GetWeakPtr() {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
return weak_ptr_factory_.GetWeakPtr();
}
@@ -552,6 +568,7 @@
void ServiceImpl::ProducerEndpointImpl::RegisterDataSource(
const DataSourceDescriptor& desc,
RegisterDataSourceCallback callback) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
DataSourceID ds_id = ++last_data_source_id_;
if (!desc.name().empty()) {
service_->RegisterDataSource(id_, ds_id, desc);
@@ -564,12 +581,14 @@
void ServiceImpl::ProducerEndpointImpl::UnregisterDataSource(
DataSourceID dsid) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
PERFETTO_CHECK(dsid);
// TODO(primiano): implement the bookkeeping logic.
}
void ServiceImpl::ProducerEndpointImpl::NotifySharedMemoryUpdate(
const std::vector<uint32_t>& changed_pages) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
for (uint32_t page_idx : changed_pages) {
if (page_idx >= shmem_abi_.num_pages())
continue; // Very likely a malicious producer playing dirty.
@@ -591,11 +610,13 @@
}
SharedMemory* ServiceImpl::ProducerEndpointImpl::shared_memory() const {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
return shared_memory_.get();
}
std::unique_ptr<TraceWriter>
ServiceImpl::ProducerEndpointImpl::CreateTraceWriter(BufferID) {
+ PERFETTO_DCHECK_THREAD(thread_checker_);
// TODO(primiano): not implemented yet.
// This code path is hit only in in-process configuration, where tracing
// Service and Producer are hosted in the same process. It's a use case we
diff --git a/src/tracing/core/service_impl.h b/src/tracing/core/service_impl.h
index ae0a2d3..0883264 100644
--- a/src/tracing/core/service_impl.h
+++ b/src/tracing/core/service_impl.h
@@ -79,6 +79,7 @@
std::unique_ptr<SharedMemory> shared_memory_;
SharedMemoryABI shmem_abi_;
DataSourceID last_data_source_id_ = 0;
+ PERFETTO_THREAD_CHECKER(thread_checker_)
};
// The implementation behind the service endpoint exposed to each consumer.
@@ -103,6 +104,9 @@
ServiceImpl* const service_;
Consumer* const consumer_;
TracingSessionID tracing_session_id_ = 0;
+
+ PERFETTO_THREAD_CHECKER(thread_checker_)
+
base::WeakPtrFactory<ConsumerEndpointImpl> weak_ptr_factory_;
};
@@ -230,6 +234,8 @@
std::map<TracingSessionID, TracingSession> tracing_sessions_;
std::map<BufferID, TraceBuffer> buffers_;
+ PERFETTO_THREAD_CHECKER(thread_checker_)
+
base::WeakPtrFactory<ServiceImpl> weak_ptr_factory_; // Keep at the end.
};
diff --git a/tools/build_all_configs.py b/tools/build_all_configs.py
index 1583661..bbf5b6e 100755
--- a/tools/build_all_configs.py
+++ b/tools/build_all_configs.py
@@ -45,7 +45,8 @@
'linux_msan': ['is_clang=true', 'is_debug=false', 'is_msan=true'],
'linux_tsan': ['is_clang=true', 'is_debug=false', 'is_tsan=true'],
'linux_ubsan': ['is_clang=true', 'is_debug=false', 'is_ubsan=true'],
- 'linux_fuzzer': ['is_clang=true', 'use_libfuzzer=true', 'is_asan=true'],
+ 'linux_fuzzer': ['is_clang=true', 'is_debug=false', 'use_libfuzzer=true',
+ 'is_asan=true', 'use_custom_libcxx=false'],
}
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))