[tracing] Add a global trace thread for PerfettoTracedProcess
This allows tracing to be logged before ThreadPoolInstance is Set for child process. This is [2/3] CL of enabling tracing prior to sandboxing. Bug: 380411640 Change-Id: I3e0a976d0e8f316d275eca8a6ab7cee2f546fd7c Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6180638 Reviewed-by: Colin Blundell <blundell@chromium.org> Reviewed-by: Alexander Timin <altimin@chromium.org> Reviewed-by: Etienne Pierre-Doray <etiennep@chromium.org> Commit-Queue: Kramer Ge <fangzhoug@chromium.org> Cr-Commit-Position: refs/heads/main@{#1421972}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
a4afb7b0b3
commit
5cccc376fe
base/tracing
chrome/windows_services/elevated_tracing_service
content
services
resource_coordinator
memory_instrumentation
public
cpp
memory_instrumentation
tracing
@ -56,11 +56,11 @@ std::unique_ptr<perfetto::base::TaskRunner> PerfettoPlatform::CreateTaskRunner(
|
||||
return perfetto_task_runner;
|
||||
}
|
||||
|
||||
void PerfettoPlatform::ResetTaskRunnerForTesting(
|
||||
void PerfettoPlatform::ResetTaskRunner(
|
||||
scoped_refptr<base::SequencedTaskRunner> task_runner) {
|
||||
task_runner_ = task_runner;
|
||||
if (perfetto_task_runner_) {
|
||||
perfetto_task_runner_->ResetTaskRunnerForTesting(task_runner); // IN-TEST
|
||||
perfetto_task_runner_->ResetTaskRunner(task_runner);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,8 +34,7 @@ class BASE_EXPORT PerfettoPlatform : public perfetto::Platform {
|
||||
// thread IDs.
|
||||
perfetto::base::PlatformThreadId GetCurrentThreadId() override;
|
||||
|
||||
void ResetTaskRunnerForTesting(
|
||||
scoped_refptr<base::SequencedTaskRunner> task_runner);
|
||||
void ResetTaskRunner(scoped_refptr<base::SequencedTaskRunner> task_runner);
|
||||
|
||||
private:
|
||||
WeakPtr<PerfettoTaskRunner> perfetto_task_runner_;
|
||||
|
@ -114,7 +114,7 @@ void PerfettoTaskRunner::RemoveFileDescriptorWatch(
|
||||
#endif // (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA)
|
||||
}
|
||||
|
||||
void PerfettoTaskRunner::ResetTaskRunnerForTesting(
|
||||
void PerfettoTaskRunner::ResetTaskRunner(
|
||||
scoped_refptr<base::SequencedTaskRunner> task_runner) {
|
||||
task_runner_ = std::move(task_runner);
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ class BASE_EXPORT PerfettoTaskRunner : public perfetto::base::TaskRunner {
|
||||
std::function<void()>) override;
|
||||
void RemoveFileDescriptorWatch(perfetto::base::PlatformHandle) override;
|
||||
|
||||
void ResetTaskRunnerForTesting(scoped_refptr<base::SequencedTaskRunner>);
|
||||
void ResetTaskRunner(scoped_refptr<base::SequencedTaskRunner>);
|
||||
|
||||
WeakPtr<PerfettoTaskRunner> GetWeakPtr() {
|
||||
return weak_factory_.GetWeakPtr();
|
||||
|
@ -128,8 +128,7 @@ bool Delegate::PreRun() {
|
||||
"elevated_tracing_service");
|
||||
|
||||
// Initialize tracing in the process.
|
||||
tracing::InitTracingPostThreadPoolStartAndFeatureList(
|
||||
/*enable_consumer=*/false);
|
||||
tracing::InitTracingPostFeatureList(/*enable_consumer=*/false);
|
||||
|
||||
// Create the global SessionRegistry.
|
||||
session_registry_ = base::MakeRefCounted<SessionRegistry>();
|
||||
|
@ -1233,8 +1233,7 @@ int ContentMainRunnerImpl::RunBrowser(MainFunctionParams main_params,
|
||||
|
||||
tracing::PerfettoTracedProcess::Get().SetAllowSystemTracingConsumerCallback(
|
||||
base::BindRepeating(&ShouldAllowSystemTracingConsumer));
|
||||
tracing::InitTracingPostThreadPoolStartAndFeatureList(
|
||||
/* enable_consumer */ true);
|
||||
tracing::InitTracingPostFeatureList(/*enable_consumer=*/true);
|
||||
|
||||
// PowerMonitor is needed in reduced mode. BrowserMainLoop will safely skip
|
||||
// initializing it again if it has already been initialized.
|
||||
|
@ -104,8 +104,7 @@ ChildProcess::ChildProcess(base::ThreadType io_thread_type,
|
||||
initialized_thread_pool_ = true;
|
||||
}
|
||||
|
||||
tracing::InitTracingPostThreadPoolStartAndFeatureList(
|
||||
/* enable_consumer */ false);
|
||||
tracing::InitTracingPostFeatureList(/*enable_consumer=*/false);
|
||||
|
||||
// Ensure the visibility tracker is created on the main thread.
|
||||
ProcessVisibilityTracker::GetInstance();
|
||||
|
@ -617,8 +617,7 @@ void BrowserTestBase::SetUp() {
|
||||
|
||||
StartBrowserThreadPool();
|
||||
|
||||
tracing::InitTracingPostThreadPoolStartAndFeatureList(
|
||||
/* enable_consumer */ true);
|
||||
tracing::InitTracingPostFeatureList(/*enable_consumer=*/true);
|
||||
InitializeBrowserMemoryInstrumentationClient();
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,7 @@ class CoordinatorImplTest : public testing::Test {
|
||||
|
||||
void SetUp() override {
|
||||
coordinator_ = std::make_unique<NiceMock<FakeCoordinatorImpl>>();
|
||||
tracing::PerfettoTracedProcess::DataSourceBase::ResetTaskRunnerForTesting(
|
||||
tracing::PerfettoTracedProcess::DataSourceBase::ResetTaskRunner(
|
||||
base::SingleThreadTaskRunner::GetCurrentDefault());
|
||||
}
|
||||
|
||||
|
@ -145,7 +145,7 @@ class MemoryTracingIntegrationTest : public testing::Test {
|
||||
coordinator_ = std::make_unique<MockCoordinator>(this);
|
||||
|
||||
TraceLog::GetInstance()->InitializePerfettoIfNeeded();
|
||||
tracing::PerfettoTracedProcess::DataSourceBase::ResetTaskRunnerForTesting(
|
||||
tracing::PerfettoTracedProcess::DataSourceBase::ResetTaskRunner(
|
||||
base::SingleThreadTaskRunner::GetCurrentDefault());
|
||||
TracingObserverProto::GetInstance()->ResetForTesting();
|
||||
}
|
||||
|
2
services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_proto_unittest.cc
2
services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_proto_unittest.cc
@ -45,7 +45,7 @@ class TracingObserverProtoTest : public testing::Test {
|
||||
false);
|
||||
memory_instrumentation::TracingObserverProto::GetInstance()
|
||||
->ResetForTesting();
|
||||
tracing::PerfettoTracedProcess::DataSourceBase::ResetTaskRunnerForTesting(
|
||||
tracing::PerfettoTracedProcess::DataSourceBase::ResetTaskRunner(
|
||||
base::SingleThreadTaskRunner::GetCurrentDefault());
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "base/no_destructor.h"
|
||||
#include "base/pickle.h"
|
||||
#include "base/process/current_process.h"
|
||||
#include "base/sequence_checker.h"
|
||||
#include "base/synchronization/lock.h"
|
||||
#include "base/time/time.h"
|
||||
#include "base/trace_event/trace_config.h"
|
||||
@ -254,6 +255,10 @@ void CustomEventRecorder::LogHistograms() {
|
||||
}
|
||||
}
|
||||
|
||||
void CustomEventRecorder::DetachFromSequence() {
|
||||
DETACH_FROM_SEQUENCE(perfetto_sequence_checker_);
|
||||
}
|
||||
|
||||
// static
|
||||
void CustomEventRecorder::OnMetricsSampleCallback(
|
||||
const char* histogram_name,
|
||||
|
@ -53,6 +53,9 @@ class COMPONENT_EXPORT(TRACING_CPP) CustomEventRecorder
|
||||
uint64_t name_hash,
|
||||
base::HistogramBase::Sample32 sample);
|
||||
bool IsPrivacyFilteringEnabled();
|
||||
// Thread can restart in Linux and ChromeOS when entering sandbox, so rebind
|
||||
// sequence checker.
|
||||
void DetachFromSequence();
|
||||
|
||||
private:
|
||||
friend class base::NoDestructor<CustomEventRecorder>;
|
||||
|
@ -12,8 +12,10 @@
|
||||
#include "base/synchronization/waitable_event.h"
|
||||
#include "base/task/sequenced_task_runner.h"
|
||||
#include "base/task/thread_pool.h"
|
||||
#include "base/threading/thread.h"
|
||||
#include "base/trace_event/trace_config.h"
|
||||
#include "base/tracing/perfetto_platform.h"
|
||||
#include "base/tracing/perfetto_task_runner.h"
|
||||
#include "build/build_config.h"
|
||||
#include "services/tracing/public/cpp/perfetto/custom_event_recorder.h"
|
||||
#include "services/tracing/public/cpp/perfetto/metadata_data_source.h"
|
||||
@ -163,11 +165,31 @@ PerfettoTracedProcess::DataSourceBase::GetTaskRunner() {
|
||||
return GetDataSourceTaskRunner().get();
|
||||
}
|
||||
|
||||
void PerfettoTracedProcess::DataSourceBase::ResetTaskRunnerForTesting(
|
||||
void PerfettoTracedProcess::DataSourceBase::ResetTaskRunner(
|
||||
scoped_refptr<base::SequencedTaskRunner> task_runner) {
|
||||
GetDataSourceTaskRunner() = task_runner;
|
||||
}
|
||||
|
||||
// static
|
||||
void PerfettoTracedProcess::RestartThreadInSandbox() {
|
||||
base::Thread* trace_thread = PerfettoTracedProcess::GetTraceThread();
|
||||
if (trace_thread->StartWithOptions(
|
||||
base::Thread::Options(base::MessagePumpType::IO, 0))) {
|
||||
DETACH_FROM_SEQUENCE(PerfettoTracedProcess::Get().sequence_checker_);
|
||||
PerfettoTracedProcess::Get().task_runner_ = trace_thread->task_runner();
|
||||
PerfettoTracedProcess::Get().platform_->ResetTaskRunner(
|
||||
trace_thread->task_runner());
|
||||
DataSourceBase::ResetTaskRunner(trace_thread->task_runner());
|
||||
PerfettoTracedProcess::Get().tracing_backend_->DetachFromMuxerSequence();
|
||||
CustomEventRecorder::GetInstance()->DetachFromSequence();
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
base::Thread* PerfettoTracedProcess::GetTraceThread() {
|
||||
return PerfettoTracedProcess::Get().trace_process_thread_.get();
|
||||
}
|
||||
|
||||
// static
|
||||
PerfettoTracedProcess& PerfettoTracedProcess::MaybeCreateInstance() {
|
||||
static base::NoDestructor<PerfettoTracedProcess> traced_process(
|
||||
@ -176,6 +198,12 @@ PerfettoTracedProcess& PerfettoTracedProcess::MaybeCreateInstance() {
|
||||
return *traced_process;
|
||||
}
|
||||
|
||||
// static
|
||||
PerfettoTracedProcess& PerfettoTracedProcess::MaybeCreateInstanceWithThread() {
|
||||
static base::NoDestructor<PerfettoTracedProcess> traced_process{};
|
||||
return *traced_process;
|
||||
}
|
||||
|
||||
// static
|
||||
PerfettoTracedProcess& PerfettoTracedProcess::MaybeCreateInstanceForTesting() {
|
||||
static base::NoDestructor<PerfettoTracedProcess> traced_process(nullptr);
|
||||
@ -188,6 +216,22 @@ PerfettoTracedProcess& PerfettoTracedProcess::Get() {
|
||||
return *g_instance;
|
||||
}
|
||||
|
||||
PerfettoTracedProcess::PerfettoTracedProcess()
|
||||
: trace_process_thread_(std::make_unique<base::Thread>("PerfettoTrace")),
|
||||
task_runner_(trace_process_thread_->StartWithOptions(
|
||||
base::Thread::Options(base::MessagePumpType::IO, 0))
|
||||
? trace_process_thread_->task_runner()
|
||||
: nullptr),
|
||||
platform_(
|
||||
std::make_unique<base::tracing::PerfettoPlatform>(task_runner_)),
|
||||
tracing_backend_(std::make_unique<PerfettoTracingBackend>()) {
|
||||
DETACH_FROM_SEQUENCE(sequence_checker_);
|
||||
CHECK_EQ(g_instance, nullptr);
|
||||
CHECK(task_runner_);
|
||||
g_instance = this;
|
||||
GetDataSourceTaskRunner() = task_runner_;
|
||||
}
|
||||
|
||||
PerfettoTracedProcess::PerfettoTracedProcess(
|
||||
scoped_refptr<base::SequencedTaskRunner> task_runner)
|
||||
: task_runner_(task_runner),
|
||||
@ -227,8 +271,8 @@ void PerfettoTracedProcess::SetupForTesting(
|
||||
DCHECK(!perfetto::Tracing::IsInitialized());
|
||||
|
||||
task_runner_ = std::move(task_runner);
|
||||
platform_->ResetTaskRunnerForTesting(task_runner_); // IN-TEST
|
||||
DataSourceBase::ResetTaskRunnerForTesting(task_runner_); // IN-TEST
|
||||
platform_->ResetTaskRunner(task_runner_);
|
||||
DataSourceBase::ResetTaskRunner(task_runner_);
|
||||
|
||||
tracing_backend_ = std::make_unique<PerfettoTracingBackend>();
|
||||
OnThreadPoolAvailable(
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "third_party/perfetto/include/perfetto/tracing/tracing_policy.h"
|
||||
|
||||
namespace base {
|
||||
class Thread;
|
||||
namespace trace_event {
|
||||
class TraceConfig;
|
||||
} // namespace trace_event
|
||||
@ -98,7 +99,7 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final
|
||||
// allows overriding that task runner.
|
||||
virtual base::SequencedTaskRunner* GetTaskRunner();
|
||||
|
||||
static void ResetTaskRunnerForTesting(
|
||||
static void ResetTaskRunner(
|
||||
scoped_refptr<base::SequencedTaskRunner> task_runner);
|
||||
|
||||
protected:
|
||||
@ -151,8 +152,16 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final
|
||||
perfetto::DataSourceConfig data_source_config_;
|
||||
};
|
||||
|
||||
// Restart the trace thread and replace the task_runner for tracing.
|
||||
static void RestartThreadInSandbox();
|
||||
|
||||
// Returns the process-wide ptr to the trace thread, returns nullptr if the
|
||||
// task_runner for tracing is from the thread-pool.
|
||||
static base::Thread* GetTraceThread();
|
||||
|
||||
// Creates the process-wide instance of the PerfettoTracedProcess.
|
||||
static PerfettoTracedProcess& MaybeCreateInstance();
|
||||
static PerfettoTracedProcess& MaybeCreateInstanceWithThread();
|
||||
static PerfettoTracedProcess& MaybeCreateInstanceForTesting();
|
||||
|
||||
// Returns the process-wide instance of the PerfettoTracedProcess.
|
||||
@ -222,8 +231,10 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final
|
||||
private:
|
||||
friend class base::NoDestructor<PerfettoTracedProcess>;
|
||||
|
||||
PerfettoTracedProcess(
|
||||
scoped_refptr<base::SequencedTaskRunner> task_runner = nullptr);
|
||||
// Default constructor would create a dedicated thread for tracing
|
||||
PerfettoTracedProcess();
|
||||
explicit PerfettoTracedProcess(
|
||||
scoped_refptr<base::SequencedTaskRunner> task_runner);
|
||||
|
||||
// Initialize the Perfetto client library (i.e., perfetto::Tracing) for this
|
||||
// process.
|
||||
@ -247,6 +258,7 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final
|
||||
bool system_consumer_enabled_for_testing_
|
||||
GUARDED_BY(allow_system_consumer_lock_) = false;
|
||||
|
||||
std::unique_ptr<base::Thread> trace_process_thread_;
|
||||
scoped_refptr<base::SequencedTaskRunner> task_runner_;
|
||||
|
||||
// Platform implementation for the Perfetto client library.
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/memory/shared_memory_switch.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/sequence_checker.h"
|
||||
#include "base/task/sequenced_task_runner.h"
|
||||
#include "base/tracing/tracing_tls.h"
|
||||
#include "base/unguessable_token.h"
|
||||
@ -80,6 +81,8 @@ class ProducerEndpoint : public perfetto::ProducerEndpoint,
|
||||
return weak_factory_.GetWeakPtr();
|
||||
}
|
||||
|
||||
void DetachFromSequence() { DETACH_FROM_SEQUENCE(sequence_checker_); }
|
||||
|
||||
// perfetto::ProducerEndpoint implementation:
|
||||
void Disconnect() override {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
@ -757,10 +760,41 @@ void PerfettoTracingBackend::OnProducerConnected(
|
||||
}
|
||||
}
|
||||
|
||||
void PerfettoTracingBackend::DetachFromMuxerSequence() {
|
||||
DETACH_FROM_SEQUENCE(muxer_sequence_checker_);
|
||||
#if DCHECK_IS_ON()
|
||||
perfetto::base::TaskRunner* task_runner;
|
||||
{
|
||||
base::AutoLock lock(task_runner_lock_);
|
||||
task_runner = muxer_task_runner_;
|
||||
}
|
||||
|
||||
// Must reset sequence_checker on `task_runner`, because `weak_this` and
|
||||
// `producer_endpoint_` needs to bind there.
|
||||
task_runner->PostTask([weak_this = weak_factory_.GetWeakPtr()] {
|
||||
// Can be destroyed in testing.
|
||||
if (weak_this && weak_this->producer_endpoint_) {
|
||||
weak_this->producer_endpoint_->DetachFromSequence();
|
||||
}
|
||||
});
|
||||
#endif // DCHECK_IS_ON()
|
||||
}
|
||||
|
||||
void PerfettoTracingBackend::BindProducerConnectionIfNecessary() {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(muxer_sequence_checker_);
|
||||
if (!producer_endpoint_)
|
||||
{
|
||||
base::AutoLock lock(task_runner_lock_);
|
||||
// Check service existence first because mojo is initialized after
|
||||
// `muxer_task_runner_` resets. So we can avoid binding `sequence_checker`
|
||||
// in `base::WeakPtr` of `producer_endpoint_` before task resets.
|
||||
if (!perfetto_service_) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!producer_endpoint_) {
|
||||
return;
|
||||
}
|
||||
|
||||
mojo::PendingRemote<mojom::PerfettoService> perfetto_service;
|
||||
{
|
||||
@ -768,10 +802,8 @@ void PerfettoTracingBackend::BindProducerConnectionIfNecessary() {
|
||||
perfetto_service = std::move(perfetto_service_);
|
||||
}
|
||||
|
||||
if (perfetto_service) {
|
||||
producer_endpoint_->BindConnection(muxer_task_runner_,
|
||||
std::move(perfetto_service));
|
||||
}
|
||||
producer_endpoint_->BindConnection(muxer_task_runner_,
|
||||
std::move(perfetto_service));
|
||||
}
|
||||
|
||||
void PerfettoTracingBackend::CreateConsumerConnection(
|
||||
|
@ -50,6 +50,12 @@ class PerfettoTracingBackend : public perfetto::TracingBackend {
|
||||
void SetConsumerConnectionFactory(ConsumerConnectionFactory,
|
||||
scoped_refptr<base::SequencedTaskRunner>);
|
||||
|
||||
// Only called at maximum once. When the platform thread running
|
||||
// `muxer_task_runner_` restarts in sandbox, detaches
|
||||
// `muxer_sequence_checker_` as well as `ProducerEndpoint`'s
|
||||
// `sequence_checker_`.
|
||||
void DetachFromMuxerSequence();
|
||||
|
||||
// perfetto::TracingBackend implementation:
|
||||
std::unique_ptr<perfetto::ProducerEndpoint> ConnectProducer(
|
||||
const ConnectProducerArgs&) override;
|
||||
|
@ -46,10 +46,10 @@ using base::trace_event::TraceLog;
|
||||
|
||||
} // namespace
|
||||
|
||||
bool g_tracing_initialized_after_threadpool_and_featurelist = false;
|
||||
bool g_tracing_initialized_after_featurelist = false;
|
||||
|
||||
bool IsTracingInitialized() {
|
||||
return g_tracing_initialized_after_threadpool_and_featurelist;
|
||||
return g_tracing_initialized_after_featurelist;
|
||||
}
|
||||
|
||||
void EnableStartupTracingIfNeeded() {
|
||||
@ -98,11 +98,11 @@ bool EnableStartupTracingForProcess(
|
||||
return true;
|
||||
}
|
||||
|
||||
void InitTracingPostThreadPoolStartAndFeatureList(bool enable_consumer) {
|
||||
if (g_tracing_initialized_after_threadpool_and_featurelist)
|
||||
void InitTracingPostFeatureList(bool enable_consumer) {
|
||||
if (g_tracing_initialized_after_featurelist) {
|
||||
return;
|
||||
g_tracing_initialized_after_threadpool_and_featurelist = true;
|
||||
DCHECK(base::ThreadPoolInstance::Get());
|
||||
}
|
||||
g_tracing_initialized_after_featurelist = true;
|
||||
DCHECK(base::FeatureList::GetInstance());
|
||||
|
||||
// Create the PerfettoTracedProcess.
|
||||
|
@ -22,7 +22,7 @@ class CommandLine;
|
||||
|
||||
namespace tracing {
|
||||
|
||||
// Returns true if InitTracingPostThreadPoolStartAndFeatureList has been called
|
||||
// Returns true if `InitTracingPostFeatureList()` has been called
|
||||
// for this process.
|
||||
bool COMPONENT_EXPORT(TRACING_CPP) IsTracingInitialized();
|
||||
|
||||
@ -52,7 +52,7 @@ bool COMPONENT_EXPORT(TRACING_CPP)
|
||||
// |enable_consumer| should be true if the system consumer can be enabled.
|
||||
// Currently this is only the case if this is running in the browser process.
|
||||
void COMPONENT_EXPORT(TRACING_CPP)
|
||||
InitTracingPostThreadPoolStartAndFeatureList(bool enable_consumer);
|
||||
InitTracingPostFeatureList(bool enable_consumer);
|
||||
|
||||
// If tracing is enabled, grabs the current trace config & mode and tells the
|
||||
// child to begin tracing right away via startup tracing command line flags.
|
||||
|
@ -68,8 +68,7 @@ MULTIPROCESS_TEST_MAIN(InitFromLaunchParameters) {
|
||||
#if !BUILDFLAG(IS_WIN) && !BUILDFLAG(IS_FUCHSIA)
|
||||
base::FeatureList::InitInstance("", "");
|
||||
base::ThreadPoolInstance::CreateAndStartWithDefaultParams("StartupTraceTest");
|
||||
tracing::InitTracingPostThreadPoolStartAndFeatureList(
|
||||
/*enable_consumer=*/false);
|
||||
tracing::InitTracingPostFeatureList(/*enable_consumer=*/false);
|
||||
|
||||
// Simulate launching with the serialized parameters.
|
||||
EnableStartupTracingIfNeeded();
|
||||
|
Reference in New Issue
Block a user