From c44beaac28179f838d95aa2fed2571eef303ea1f Mon Sep 17 00:00:00 2001 From: Marcos Slomp Date: Tue, 2 Dec 2025 16:19:20 -0800 Subject: [PATCH 1/3] fixed race condition around s_sysTraceThread --- public/client/TracyProfiler.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/public/client/TracyProfiler.cpp b/public/client/TracyProfiler.cpp index 34caedf0..e605f83a 100644 --- a/public/client/TracyProfiler.cpp +++ b/public/client/TracyProfiler.cpp @@ -933,7 +933,7 @@ static Thread* s_symbolThread; std::atomic s_symbolThreadGone { false }; #endif #ifdef TRACY_HAS_SYSTEM_TRACING -static Thread* s_sysTraceThread = nullptr; +static std::atomic s_sysTraceThread = nullptr; #endif #if defined __linux__ && !defined TRACY_NO_CRASH_HANDLER @@ -1184,20 +1184,22 @@ static void StartSystemTracing( int64_t& samplingPeriod ) } else if( SysTraceStart( samplingPeriod ) ) { - s_sysTraceThread = (Thread*)tracy_malloc( sizeof( Thread ) ); - new(s_sysTraceThread) Thread( SysTraceWorker, nullptr ); + Thread* sysTraceThread = (Thread*)tracy_malloc( sizeof( Thread ) ); + new(sysTraceThread) Thread(SysTraceWorker, nullptr); + Thread* prev = s_sysTraceThread.exchange(sysTraceThread); + assert(prev == nullptr); std::this_thread::sleep_for( std::chrono::milliseconds( 1 ) ); } } static void StopSystemTracing() { - if( s_sysTraceThread ) + Thread* sysTraceThread = s_sysTraceThread.exchange(nullptr); + if( sysTraceThread ) { SysTraceStop(); - s_sysTraceThread->~Thread(); - tracy_free( s_sysTraceThread ); - s_sysTraceThread = nullptr; + sysTraceThread->~Thread(); + tracy_free( sysTraceThread ); } } #endif From 874d65b0368ef0ee72c0848fb2b02b7024655b27 Mon Sep 17 00:00:00 2001 From: Marcos Slomp Date: Wed, 3 Dec 2025 10:15:19 -0800 Subject: [PATCH 2/3] code formatting --- public/client/TracyProfiler.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/public/client/TracyProfiler.cpp b/public/client/TracyProfiler.cpp index e605f83a..e5f54fd3 100644 --- a/public/client/TracyProfiler.cpp +++ b/public/client/TracyProfiler.cpp @@ -1177,24 +1177,24 @@ static void StartSystemTracing( int64_t& samplingPeriod ) // use TRACY_NO_SYS_TRACE=1 to force disabling sys tracing (even if available in the underlying system) // as it can have significant impact on the size of the traces const char* noSysTrace = GetEnvVar( "TRACY_NO_SYS_TRACE" ); - const bool disableSystrace = (noSysTrace && noSysTrace[0] == '1'); + const bool disableSystrace = ( noSysTrace && noSysTrace[0] == '1' ); if( disableSystrace ) { - TracyDebug("TRACY: Sys Trace was disabled by 'TRACY_NO_SYS_TRACE=1'\n"); + TracyDebug( "TRACY: Sys Trace was disabled by 'TRACY_NO_SYS_TRACE=1'\n" ); } else if( SysTraceStart( samplingPeriod ) ) { Thread* sysTraceThread = (Thread*)tracy_malloc( sizeof( Thread ) ); - new(sysTraceThread) Thread(SysTraceWorker, nullptr); - Thread* prev = s_sysTraceThread.exchange(sysTraceThread); - assert(prev == nullptr); + new( sysTraceThread ) Thread( SysTraceWorker, nullptr ); + Thread* prev = s_sysTraceThread.exchange( sysTraceThread ); + assert( prev == nullptr ); std::this_thread::sleep_for( std::chrono::milliseconds( 1 ) ); } } static void StopSystemTracing() { - Thread* sysTraceThread = s_sysTraceThread.exchange(nullptr); + Thread* sysTraceThread = s_sysTraceThread.exchange( nullptr ); if( sysTraceThread ) { SysTraceStop(); From 7fa30d08b520fe1a3b84aca276dda30af933761c Mon Sep 17 00:00:00 2001 From: Marcos Slomp Date: Wed, 3 Dec 2025 12:41:44 -0800 Subject: [PATCH 3/3] clarification --- public/client/TracyProfiler.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/public/client/TracyProfiler.cpp b/public/client/TracyProfiler.cpp index e5f54fd3..d073f0bb 100644 --- a/public/client/TracyProfiler.cpp +++ b/public/client/TracyProfiler.cpp @@ -2148,9 +2148,15 @@ void Profiler::Worker() while( s_symbolThreadGone.load() == false ) { YieldThread(); } #endif - // Client is exiting. #ifdef TRACY_HAS_SYSTEM_TRACING - // Stop filling queues with new data. + // On a typical shutdown scenario, the (global) Profiler object is destroyed by + // the C++ runtime when the client program returns from "main", and ~Profiler() + // takes care of calling StopSystemTracing(). However, a client may decide to + // manually RequestShutdown(), in which case ~Profile() may not execute before + // this Worker() thread goes through its teardown stages and reaches this point. + // To ensure that system tracing does not keep pushing data to the worker queue + // indefinitely (thus preventing this worker from terminating), we have to call + // StopSystemTracing() here as well to be safe: StopSystemTracing(); #endif