Merge "Amalgamated source for v27.1" into releases/v27.x
diff --git a/CHANGELOG b/CHANGELOG
index 8407784..77cb981 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -9,6 +9,11 @@
*
+v27.1 - 2022-07-11:
+ SDK:
+ * Added an API for shutting down Perfetto.
+
+
v27.0 - 2022-07-01:
Tracing service and probes:
* Fix rare crash due to watchdog timeout being too short.
diff --git a/include/perfetto/tracing/tracing.h b/include/perfetto/tracing/tracing.h
index e0f95e1..89b5efd 100644
--- a/include/perfetto/tracing/tracing.h
+++ b/include/perfetto/tracing/tracing.h
@@ -177,6 +177,19 @@
static std::unique_ptr<TracingSession> NewTrace(
BackendType = kUnspecifiedBackend);
+ // Shut down Perfetto, releasing any allocated OS resources (threads, files,
+ // sockets, etc.). Note that Perfetto cannot be reinitialized again in the
+ // same process[1]. Instead, this function is meant for shutting down all
+ // Perfetto-related code so that it can be safely unloaded, e.g., with
+ // dlclose().
+ //
+ // It is only safe to call this function when all threads recording trace
+ // events have been terminated or otherwise guaranteed to not make any further
+ // calls into Perfetto.
+ //
+ // [1] Unless static data is also cleared through other means.
+ static void Shutdown();
+
// Uninitialize Perfetto. Only exposed for testing scenarios where it can be
// guaranteed that no tracing sessions or other operations are happening when
// this call is made.
diff --git a/src/tracing/internal/tracing_muxer_impl.cc b/src/tracing/internal/tracing_muxer_impl.cc
index 7f46a3a..13ba94a 100644
--- a/src/tracing/internal/tracing_muxer_impl.cc
+++ b/src/tracing/internal/tracing_muxer_impl.cc
@@ -1801,6 +1801,40 @@
}
}
+// static
+void TracingMuxerImpl::Shutdown() {
+ auto* muxer = reinterpret_cast<TracingMuxerImpl*>(instance_);
+
+ // Shutting down on the muxer thread would lead to a deadlock.
+ PERFETTO_CHECK(!muxer->task_runner_->RunsTasksOnCurrentThread());
+ muxer->DestroyStoppedTraceWritersForCurrentThread();
+
+ std::unique_ptr<base::TaskRunner> owned_task_runner(
+ muxer->task_runner_.get());
+ base::WaitableEvent shutdown_done;
+ owned_task_runner->PostTask([muxer, &shutdown_done] {
+ // Check that no consumer session is currently active on any backend.
+ // Producers will be automatically disconnected as a part of deleting the
+ // muxer below.
+ for (auto& backend : muxer->backends_) {
+ for (auto& consumer : backend.consumers) {
+ PERFETTO_CHECK(!consumer->service_);
+ }
+ }
+ // Make sure no trace writers are lingering around on the muxer thread. Note
+ // that we can't do this for any arbitrary thread in the process; it is the
+ // caller's responsibility to clean them up before shutting down Perfetto.
+ muxer->DestroyStoppedTraceWritersForCurrentThread();
+ // The task runner must be deleted outside the muxer thread. This is done by
+ // `owned_task_runner` above.
+ muxer->task_runner_.release();
+ delete muxer;
+ instance_ = TracingMuxerFake::Get();
+ shutdown_done.Notify();
+ });
+ shutdown_done.Wait();
+}
+
TracingMuxer::~TracingMuxer() = default;
static_assert(std::is_same<internal::BufferId, BufferID>::value,
diff --git a/src/tracing/internal/tracing_muxer_impl.h b/src/tracing/internal/tracing_muxer_impl.h
index 1841cd4..d0f0dac 100644
--- a/src/tracing/internal/tracing_muxer_impl.h
+++ b/src/tracing/internal/tracing_muxer_impl.h
@@ -98,6 +98,7 @@
static void InitializeInstance(const TracingInitArgs&);
static void ResetForTesting();
+ static void Shutdown();
// TracingMuxer implementation.
bool RegisterDataSource(const DataSourceDescriptor&,
diff --git a/src/tracing/test/api_integrationtest.cc b/src/tracing/test/api_integrationtest.cc
index a25ccfa..c09dfc5 100644
--- a/src/tracing/test/api_integrationtest.cc
+++ b/src/tracing/test/api_integrationtest.cc
@@ -492,6 +492,20 @@
perfetto::Tracing::ResetForTesting();
}
+ static void TearDownTestSuite() {
+ // Test shutting down Perfetto only when all other tests have been run and
+ // no more tracing code will be executed.
+ PERFETTO_CHECK(!perfetto::Tracing::IsInitialized());
+ TracingInitArgs args;
+ args.backends = perfetto::kInProcessBackend;
+ perfetto::Tracing::Initialize(args);
+ perfetto::Tracing::Shutdown();
+ PERFETTO_CHECK(!perfetto::Tracing::IsInitialized());
+ // Shutting down again is a no-op.
+ perfetto::Tracing::Shutdown();
+ PERFETTO_CHECK(!perfetto::Tracing::IsInitialized());
+ }
+
template <typename DataSourceType>
TestDataSourceHandle* RegisterDataSource(std::string name) {
perfetto::DataSourceDescriptor dsd;
diff --git a/src/tracing/tracing.cc b/src/tracing/tracing.cc
index adaffad..f23136f 100644
--- a/src/tracing/tracing.cc
+++ b/src/tracing/tracing.cc
@@ -68,6 +68,15 @@
}
// static
+void Tracing::Shutdown() {
+ std::unique_lock<std::mutex> lock(InitializedMutex());
+ if (!g_was_initialized)
+ return;
+ internal::TracingMuxerImpl::Shutdown();
+ g_was_initialized = false;
+}
+
+// static
void Tracing::ResetForTesting() {
std::unique_lock<std::mutex> lock(InitializedMutex());
if (!g_was_initialized)