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__)))