diff --git a/public/client/TracyProfiler.cpp b/public/client/TracyProfiler.cpp index 1175bc6fe4..6c965642bf 100644 --- a/public/client/TracyProfiler.cpp +++ b/public/client/TracyProfiler.cpp @@ -909,6 +909,7 @@ static Profiler* s_instance = nullptr; static Thread* s_thread; #ifndef TRACY_NO_FRAME_IMAGE static Thread* s_compressThread; +std::atomic s_compressThreadGone { false }; #endif #ifdef TRACY_HAS_CALLSTACK static Thread* s_symbolThread; @@ -916,6 +917,7 @@ std::atomic s_symbolThreadGone { false }; #endif #ifdef TRACY_HAS_SYSTEM_TRACING static std::atomic s_sysTraceThread(nullptr); +std::atomic s_sysTraceThreadGone { false }; #endif #if defined __linux__ && !defined TRACY_NO_CRASH_HANDLER @@ -1175,6 +1177,7 @@ static void StartSystemTracing( int64_t& samplingPeriod ) new( sysTraceThread ) Thread( SysTraceWorker, nullptr ); Thread* prev = s_sysTraceThread.exchange( sysTraceThread ); assert( prev == nullptr ); + s_sysTraceThreadGone.store( false ); std::this_thread::sleep_for( std::chrono::milliseconds( 1 ) ); } } @@ -1185,6 +1188,7 @@ static void StopSystemTracing() if( sysTraceThread ) { SysTraceStop(); + while( s_sysTraceThreadGone.load() == false ) { YieldThread(); } sysTraceThread->~Thread(); tracy_free( sysTraceThread ); } @@ -1617,11 +1621,13 @@ void Profiler::SpawnWorkerThreads() #ifndef TRACY_NO_FRAME_IMAGE s_compressThread = (Thread*)tracy_malloc( sizeof( Thread ) ); new(s_compressThread) Thread( LaunchCompressWorker, this ); + s_compressThreadGone.store( false ); #endif #ifdef TRACY_HAS_CALLSTACK s_symbolThread = (Thread*)tracy_malloc( sizeof( Thread ) ); new(s_symbolThread) Thread( LaunchSymbolWorker, this ); + s_symbolThreadGone.store( false ); #endif #if defined _WIN32 && !defined TRACY_WIN32_NO_DESKTOP && !defined TRACY_NO_CRASH_HANDLER @@ -1649,15 +1655,18 @@ Profiler::~Profiler() #endif #ifdef TRACY_HAS_CALLSTACK + while( s_symbolThreadGone.load() == false ) { YieldThread(); } s_symbolThread->~Thread(); tracy_free( s_symbolThread ); #endif #ifndef TRACY_NO_FRAME_IMAGE + while( s_compressThreadGone.load() == false ) { YieldThread(); } s_compressThread->~Thread(); tracy_free( s_compressThread ); #endif + while( m_shutdownFinished.load() == false ) { YieldThread(); } s_thread->~Thread(); tracy_free( s_thread ); @@ -2296,6 +2305,7 @@ void Profiler::CompressWorker() if( shouldExit ) { + s_compressThreadGone.store( true, std::memory_order_release ); return; } } diff --git a/public/client/TracySysTrace.cpp b/public/client/TracySysTrace.cpp index 0d80e5b877..53bb1b7e53 100644 --- a/public/client/TracySysTrace.cpp +++ b/public/client/TracySysTrace.cpp @@ -1395,6 +1395,7 @@ void SysTraceWorker( void* ptr ) for( int i=0; i +# include +# include #else # include #endif @@ -43,7 +45,10 @@ class Thread ~Thread() { - WaitForSingleObject( m_hnd, INFINITE ); + // Here we can't use WaitForSingleObject( m_hnd, INFINITE ); because during DLL unload + // this destructor may run inside DllMain. Waiting on a thread in DllMain is forbidden + // and can lead to a "loader lock" deadlock. + std::this_thread::sleep_for( std::chrono::milliseconds( 20 ) ); CloseHandle( m_hnd ); }