diff --git a/public/client/TracyProfiler.cpp b/public/client/TracyProfiler.cpp index 762fd9a7..0691f78e 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 @@ -1177,27 +1177,29 @@ 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 ) ) { - 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 @@ -2146,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