From 93787182312884cedf0d59b4c7a2bd7639581b17 Mon Sep 17 00:00:00 2001 From: Joshua Kriegshauser Date: Mon, 23 Sep 2024 12:00:39 -0700 Subject: [PATCH 1/8] Safe copy --- public/client/TracyProfiler.cpp | 37 +++++++++++++--- public/client/TracyProfiler.hpp | 77 +++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 7 deletions(-) diff --git a/public/client/TracyProfiler.cpp b/public/client/TracyProfiler.cpp index bb0ca7c8..f7ad5c6b 100644 --- a/public/client/TracyProfiler.cpp +++ b/public/client/TracyProfiler.cpp @@ -111,6 +111,7 @@ extern "C" typedef char* (WINAPI *t_WineGetBuildId)(); #else # include # include +# include #endif #if defined __linux__ # include @@ -1462,6 +1463,22 @@ Profiler::Profiler() m_userPort = atoi( userPort ); } + m_safeSendBufferSize = 65536; + m_safeSendBuffer = (char*)tracy_malloc( m_safeSendBufferSize ); + +#ifndef _WIN32 + pipe(m_pipe); +# if defined __APPLE__ || defined BSD + // FreeBSD/XNU don't have F_SETPIPE_SZ, so use the default + m_pipeBufSize = 16384; +# else + m_pipeBufSize = (int)(ptrdiff_t)m_safeSendBufferSize; + while( fcntl( m_pipe[0], F_SETPIPE_SZ, m_pipeBufSize ) == -1 && errno == EPERM ) + m_pipeBufSize /= 2; // too big; reduce + m_pipeBufSize = fcntl( m_pipe[0], F_GETPIPE_SZ ); +# endif +#endif + #if !defined(TRACY_DELAYED_INIT) || !defined(TRACY_MANUAL_LIFETIME) SpawnWorkerThreads(); #endif @@ -1487,7 +1504,7 @@ void Profiler::InstallCrashHandler() #endif #if defined _WIN32 && !defined TRACY_UWP && !defined TRACY_NO_CRASH_HANDLER - m_exceptionHandler = AddVectoredExceptionHandler( 1, CrashFilter ); + m_exceptionHandler = AddVectoredExceptionHandler( 0, CrashFilter ); #endif #ifndef TRACY_NO_CRASH_HANDLER @@ -1600,6 +1617,12 @@ Profiler::~Profiler() tracy_free( m_kcore ); #endif +#ifndef _WIN32 + close( m_pipe[0] ); + close( m_pipe[1] ); +#endif + tracy_free( m_safeSendBuffer ); + tracy_free( m_lz4Buf ); tracy_free( m_buffer ); LZ4_freeStream( (LZ4_stream_t*)m_stream ); @@ -4017,13 +4040,13 @@ void Profiler::HandleSymbolCodeQuery( uint64_t symbol, uint32_t size ) } else { - if( !EnsureReadable( symbol ) ) - { - AckSymbolCodeNotAvailable(); + // 'symbol' may have come from a module that has since unloaded, perform a safe copy before sending + if( withSafeCopy( (const char*)symbol, size, [this, symbol]( const char* buf, size_t size ) { + SendLongString( symbol, buf, size, QueueType::SymbolCode ); + })) return; - } - - SendLongString( symbol, (const char*)symbol, size, QueueType::SymbolCode ); + + AckSymbolCodeNotAvailable(); } } diff --git a/public/client/TracyProfiler.hpp b/public/client/TracyProfiler.hpp index 46f11f3d..b8b132ea 100644 --- a/public/client/TracyProfiler.hpp +++ b/public/client/TracyProfiler.hpp @@ -833,6 +833,72 @@ private: m_bufferOffset += int( len ); } + template // must be void(const char* buf, size_t size) + bool withSafeCopy(const char* p, size_t size, Callable&& callable) + { + bool success = true, heap = false; + char* buf = m_safeSendBuffer; + +#ifndef NDEBUG + assert( !m_inUse.exchange(true) ); +#endif + + if( size > m_safeSendBufferSize ) + { + heap = true; + buf = (char*)tracy_malloc( size ); + } + +#ifdef _WIN32 + __try + { + memcpy( buf, p, size ); + } + __except( 1 /*EXCEPTION_EXECUTE_HANDLER*/ ) + { + success = false; + } +#else + // Send through the pipe to ensure safe reads + for( size_t offset = 0; offset != size; /*in loop*/ ) + { + size_t sendsize = std::min( size - offset, (size_t)(ptrdiff_t)m_pipeBufSize ); + ssize_t result1, result2; + while( ( result1 = write( m_pipe[1], p + offset, sendsize ) ) < 0 && errno == EINTR ) + /* retry */; + if( result1 < 0 ) + { + success = false; + break; + } + while( ( result2 = read( m_pipe[0], buf + offset, result1 ) ) < 0 && errno == EINTR ) + /* retry */; + if( result2 != result1 ) + { + success = false; + break; + } + offset += result1; + } +#endif + + if( success ) + { + callable( buf, size ); + } + + if( heap ) + { + tracy_free( buf ); + } + +#ifndef NDEBUG + m_inUse.store( false ); +#endif + + return success; + } + bool SendData( const char* data, size_t len ); void SendLongString( uint64_t ptr, const char* str, size_t len, QueueType type ); void SendSourceLocation( uint64_t ptr ); @@ -990,9 +1056,20 @@ private: char* m_queryData; char* m_queryDataPtr; +#ifndef NDEBUG + // m_safeSendBuffer and m_pipe should only be used by the Tracy Profiler thread; this ensures that in debug builds. + std::atomic_bool m_inUse{ false }; +#endif + char* m_safeSendBuffer; + size_t m_safeSendBufferSize; + #if defined _WIN32 void* m_exceptionHandler; +#else + int m_pipe[2]; + int m_pipeBufSize; #endif + #ifdef __linux__ struct { struct sigaction pwr, ill, fpe, segv, pipe, bus, abrt; From 5213c53bb065d40f6cfc60de2048a43d24646604 Mon Sep 17 00:00:00 2001 From: Joshua Kriegshauser Date: Tue, 24 Sep 2024 09:20:04 -0700 Subject: [PATCH 2/8] Use SetUnhandledExceptionFilter instead of vectored exceptions --- public/client/TracyProfiler.cpp | 20 ++++++++++++++------ public/client/TracyProfiler.hpp | 4 +--- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/public/client/TracyProfiler.cpp b/public/client/TracyProfiler.cpp index f7ad5c6b..fc42268b 100644 --- a/public/client/TracyProfiler.cpp +++ b/public/client/TracyProfiler.cpp @@ -1501,14 +1501,17 @@ void Profiler::InstallCrashHandler() sigaction( SIGPIPE, &crashHandler, &m_prevSignal.pipe ); sigaction( SIGBUS, &crashHandler, &m_prevSignal.bus ); sigaction( SIGABRT, &crashHandler, &m_prevSignal.abrt ); + + m_crashHandlerInstalled = true; #endif #if defined _WIN32 && !defined TRACY_UWP && !defined TRACY_NO_CRASH_HANDLER - m_exceptionHandler = AddVectoredExceptionHandler( 0, CrashFilter ); -#endif - -#ifndef TRACY_NO_CRASH_HANDLER - m_crashHandlerInstalled = true; + // We cannot use Vectored Exception handling because it catches application-wide frame-based SEH blocks. We only + // want to catch unhandled exceptions in the event that there is not already an unhandled exception filter. + if( auto prev = SetUnhandledExceptionFilter( CrashFilter ) ) + SetUnhandledExceptionFilter( prev ); // Already had a handler => put it back + else + m_crashHandlerInstalled = true; #endif } @@ -1516,7 +1519,12 @@ void Profiler::InstallCrashHandler() void Profiler::RemoveCrashHandler() { #if defined _WIN32 && !defined TRACY_UWP - if( m_crashHandlerInstalled ) RemoveVectoredExceptionHandler( m_exceptionHandler ); + if( m_crashHandlerInstalled ) + { + auto prev = SetUnhandledExceptionFilter( NULL ); + if( prev != CrashFilter ) + SetUnhandledExceptionFilter( prev ); // A different exception filter was installed over ours => put it back + } #endif #if defined __linux__ && !defined TRACY_NO_CRASH_HANDLER diff --git a/public/client/TracyProfiler.hpp b/public/client/TracyProfiler.hpp index b8b132ea..b559a71b 100644 --- a/public/client/TracyProfiler.hpp +++ b/public/client/TracyProfiler.hpp @@ -1063,9 +1063,7 @@ private: char* m_safeSendBuffer; size_t m_safeSendBufferSize; -#if defined _WIN32 - void* m_exceptionHandler; -#else +#ifndef _WIN32 int m_pipe[2]; int m_pipeBufSize; #endif From 201dcb6a8a576fcdf97894db5038c55f06266cb5 Mon Sep 17 00:00:00 2001 From: Joshua Kriegshauser Date: Tue, 24 Sep 2024 13:48:40 -0700 Subject: [PATCH 3/8] Tweaks --- public/client/TracyProfiler.cpp | 3 ++- public/client/TracyProfiler.hpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/public/client/TracyProfiler.cpp b/public/client/TracyProfiler.cpp index fc42268b..6061f2ff 100644 --- a/public/client/TracyProfiler.cpp +++ b/public/client/TracyProfiler.cpp @@ -1473,10 +1473,11 @@ Profiler::Profiler() m_pipeBufSize = 16384; # else m_pipeBufSize = (int)(ptrdiff_t)m_safeSendBufferSize; - while( fcntl( m_pipe[0], F_SETPIPE_SZ, m_pipeBufSize ) == -1 && errno == EPERM ) + while( fcntl( m_pipe[0], F_SETPIPE_SZ, m_pipeBufSize ) < 0 && errno == EPERM ) m_pipeBufSize /= 2; // too big; reduce m_pipeBufSize = fcntl( m_pipe[0], F_GETPIPE_SZ ); # endif + fcntl( m_pipe[1], F_SETFL, O_NONBLOCK ); #endif #if !defined(TRACY_DELAYED_INIT) || !defined(TRACY_MANUAL_LIFETIME) diff --git a/public/client/TracyProfiler.hpp b/public/client/TracyProfiler.hpp index b559a71b..69707de1 100644 --- a/public/client/TracyProfiler.hpp +++ b/public/client/TracyProfiler.hpp @@ -862,7 +862,7 @@ private: // Send through the pipe to ensure safe reads for( size_t offset = 0; offset != size; /*in loop*/ ) { - size_t sendsize = std::min( size - offset, (size_t)(ptrdiff_t)m_pipeBufSize ); + size_t sendsize = size - offset; ssize_t result1, result2; while( ( result1 = write( m_pipe[1], p + offset, sendsize ) ) < 0 && errno == EINTR ) /* retry */; From cc860fe56a70e2f344395c70dc42d9ffbf95b05a Mon Sep 17 00:00:00 2001 From: Joshua Kriegshauser Date: Tue, 24 Sep 2024 15:10:42 -0700 Subject: [PATCH 4/8] Reduce template code --- public/client/TracyProfiler.cpp | 65 ++++++++++++++++++++++++++++++- public/client/TracyProfiler.hpp | 69 +++++---------------------------- 2 files changed, 73 insertions(+), 61 deletions(-) diff --git a/public/client/TracyProfiler.cpp b/public/client/TracyProfiler.cpp index 6061f2ff..4308cf38 100644 --- a/public/client/TracyProfiler.cpp +++ b/public/client/TracyProfiler.cpp @@ -3095,6 +3095,69 @@ bool Profiler::CommitData() return ret; } +char* Profiler::SafeCopyProlog( const char* data, size_t size ) +{ + bool success = true; + char* buf = m_safeSendBuffer; +#ifndef NDEBUG + assert( !m_inUse.exchange(true) ); +#endif + + if( size > m_safeSendBufferSize ) + { + buf = (char*)tracy_malloc( size ); + } + +#ifdef _WIN32 + __try + { + memcpy( buf, data, size ); + } + __except( 1 /*EXCEPTION_EXECUTE_HANDLER*/ ) + { + success = false; + } +#else + // Send through the pipe to ensure safe reads + for( size_t offset = 0; offset != size; /*in loop*/ ) + { + size_t sendsize = size - offset; + ssize_t result1, result2; + while( ( result1 = write( m_pipe[1], data + offset, sendsize ) ) < 0 && errno == EINTR ) + /* retry */; + if( result1 < 0 ) + { + success = false; + break; + } + while( ( result2 = read( m_pipe[0], buf + offset, result1 ) ) < 0 && errno == EINTR ) + /* retry */; + if( result2 != result1 ) + { + success = false; + break; + } + offset += result1; + } +#endif + + if( success ) + return buf; + + SafeCopyEpilog( buf ); + return nullptr; +} + +void Profiler::SafeCopyEpilog( char* buf ) +{ + if( buf != m_safeSendBuffer ) + tracy_free( buf ); + +#ifndef NDEBUG + m_inUse.store( false ); +#endif +} + bool Profiler::SendData( const char* data, size_t len ) { const lz4sz_t lz4sz = LZ4_compress_fast_continue( (LZ4_stream_t*)m_stream, data, m_lz4Buf + sizeof( lz4sz_t ), (int)len, LZ4Size, 1 ); @@ -4050,7 +4113,7 @@ void Profiler::HandleSymbolCodeQuery( uint64_t symbol, uint32_t size ) else { // 'symbol' may have come from a module that has since unloaded, perform a safe copy before sending - if( withSafeCopy( (const char*)symbol, size, [this, symbol]( const char* buf, size_t size ) { + if( WithSafeCopy( (const char*)symbol, size, [this, symbol]( const char* buf, size_t size ) { SendLongString( symbol, buf, size, QueueType::SymbolCode ); })) return; diff --git a/public/client/TracyProfiler.hpp b/public/client/TracyProfiler.hpp index 69707de1..f736a926 100644 --- a/public/client/TracyProfiler.hpp +++ b/public/client/TracyProfiler.hpp @@ -833,70 +833,19 @@ private: m_bufferOffset += int( len ); } - template // must be void(const char* buf, size_t size) - bool withSafeCopy(const char* p, size_t size, Callable&& callable) + char* SafeCopyProlog( const char* p, size_t size ); + void SafeCopyEpilog( char* buf ); + + template // must be void( const char* buf, size_t size ) + bool WithSafeCopy( const char* p, size_t size, Callable&& callable ) { - bool success = true, heap = false; - char* buf = m_safeSendBuffer; - -#ifndef NDEBUG - assert( !m_inUse.exchange(true) ); -#endif - - if( size > m_safeSendBufferSize ) - { - heap = true; - buf = (char*)tracy_malloc( size ); - } - -#ifdef _WIN32 - __try - { - memcpy( buf, p, size ); - } - __except( 1 /*EXCEPTION_EXECUTE_HANDLER*/ ) - { - success = false; - } -#else - // Send through the pipe to ensure safe reads - for( size_t offset = 0; offset != size; /*in loop*/ ) - { - size_t sendsize = size - offset; - ssize_t result1, result2; - while( ( result1 = write( m_pipe[1], p + offset, sendsize ) ) < 0 && errno == EINTR ) - /* retry */; - if( result1 < 0 ) - { - success = false; - break; - } - while( ( result2 = read( m_pipe[0], buf + offset, result1 ) ) < 0 && errno == EINTR ) - /* retry */; - if( result2 != result1 ) - { - success = false; - break; - } - offset += result1; - } -#endif - - if( success ) + if( char* buf = SafeCopyProlog( p, size ) ) { callable( buf, size ); + SafeCopyEpilog( buf ); + return true; } - - if( heap ) - { - tracy_free( buf ); - } - -#ifndef NDEBUG - m_inUse.store( false ); -#endif - - return success; + return false; } bool SendData( const char* data, size_t len ); From 97a6a3dde72d9d3c2780bc2506ea3c048c9ea151 Mon Sep 17 00:00:00 2001 From: Joshua Kriegshauser Date: Thu, 26 Sep 2024 09:00:35 -0700 Subject: [PATCH 5/8] always override unhandled exception filter --- public/client/TracyProfiler.cpp | 37 +++++++++++++++++++-------------- public/client/TracyProfiler.hpp | 4 +++- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/public/client/TracyProfiler.cpp b/public/client/TracyProfiler.cpp index 4308cf38..a43bc831 100644 --- a/public/client/TracyProfiler.cpp +++ b/public/client/TracyProfiler.cpp @@ -1502,27 +1502,26 @@ void Profiler::InstallCrashHandler() sigaction( SIGPIPE, &crashHandler, &m_prevSignal.pipe ); sigaction( SIGBUS, &crashHandler, &m_prevSignal.bus ); sigaction( SIGABRT, &crashHandler, &m_prevSignal.abrt ); - - m_crashHandlerInstalled = true; #endif #if defined _WIN32 && !defined TRACY_UWP && !defined TRACY_NO_CRASH_HANDLER // We cannot use Vectored Exception handling because it catches application-wide frame-based SEH blocks. We only - // want to catch unhandled exceptions in the event that there is not already an unhandled exception filter. - if( auto prev = SetUnhandledExceptionFilter( CrashFilter ) ) - SetUnhandledExceptionFilter( prev ); // Already had a handler => put it back - else - m_crashHandlerInstalled = true; + // want to catch unhandled exceptions. + m_prevHandler = SetUnhandledExceptionFilter( CrashFilter ); +#endif + +#ifndef TRACY_NO_CRASH_HANDLER + m_crashHandlerInstalled = true; #endif } void Profiler::RemoveCrashHandler() { -#if defined _WIN32 && !defined TRACY_UWP +#if defined _WIN32 && !defined TRACY_UWP && !defined TRACY_NO_CRASH_HANDLER if( m_crashHandlerInstalled ) { - auto prev = SetUnhandledExceptionFilter( NULL ); + auto prev = SetUnhandledExceptionFilter( (LPTOP_LEVEL_EXCEPTION_FILTER)m_prevHandler ); if( prev != CrashFilter ) SetUnhandledExceptionFilter( prev ); // A different exception filter was installed over ours => put it back } @@ -1531,13 +1530,19 @@ void Profiler::RemoveCrashHandler() #if defined __linux__ && !defined TRACY_NO_CRASH_HANDLER if( m_crashHandlerInstalled ) { - sigaction( TRACY_CRASH_SIGNAL, &m_prevSignal.pwr, nullptr ); - sigaction( SIGILL, &m_prevSignal.ill, nullptr ); - sigaction( SIGFPE, &m_prevSignal.fpe, nullptr ); - sigaction( SIGSEGV, &m_prevSignal.segv, nullptr ); - sigaction( SIGPIPE, &m_prevSignal.pipe, nullptr ); - sigaction( SIGBUS, &m_prevSignal.bus, nullptr ); - sigaction( SIGABRT, &m_prevSignal.abrt, nullptr ); + auto restore = [this]( int signum, struct sigaction* prev ) { + struct sigaction old; + sigaction( signum, prev, &old ); + if( old.sa_sigaction != CrashHandler ) + sigaction( signum, &old, nullptr ); // A different signal handler was installed over ours => put it back + }; + restore( TRACY_CRASH_SIGNAL, &m_prevSignal.pwr ); + restore( SIGILL, &m_prevSignal.ill ); + restore( SIGFPE, &m_prevSignal.fpe ); + restore( SIGSEGV, &m_prevSignal.segv ); + restore( SIGPIPE, &m_prevSignal.pipe ); + restore( SIGBUS, &m_prevSignal.bus ); + restore( SIGABRT, &m_prevSignal.abrt ); } #endif m_crashHandlerInstalled = false; diff --git a/public/client/TracyProfiler.hpp b/public/client/TracyProfiler.hpp index f736a926..2fbaf9b4 100644 --- a/public/client/TracyProfiler.hpp +++ b/public/client/TracyProfiler.hpp @@ -1012,7 +1012,9 @@ private: char* m_safeSendBuffer; size_t m_safeSendBufferSize; -#ifndef _WIN32 +#if defined _WIN32 + void* m_prevHandler; +#else int m_pipe[2]; int m_pipeBufSize; #endif From 9dfb1e98b96e62bfdd45199226141331109aff07 Mon Sep 17 00:00:00 2001 From: Joshua Kriegshauser Date: Mon, 30 Sep 2024 20:22:13 -0700 Subject: [PATCH 6/8] Line and braces tweaks --- public/client/TracyProfiler.cpp | 39 ++++++++++++--------------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/public/client/TracyProfiler.cpp b/public/client/TracyProfiler.cpp index a43bc831..20738ac2 100644 --- a/public/client/TracyProfiler.cpp +++ b/public/client/TracyProfiler.cpp @@ -1473,8 +1473,7 @@ Profiler::Profiler() m_pipeBufSize = 16384; # else m_pipeBufSize = (int)(ptrdiff_t)m_safeSendBufferSize; - while( fcntl( m_pipe[0], F_SETPIPE_SZ, m_pipeBufSize ) < 0 && errno == EPERM ) - m_pipeBufSize /= 2; // too big; reduce + while( fcntl( m_pipe[0], F_SETPIPE_SZ, m_pipeBufSize ) < 0 && errno == EPERM ) m_pipeBufSize /= 2; // too big; reduce m_pipeBufSize = fcntl( m_pipe[0], F_GETPIPE_SZ ); # endif fcntl( m_pipe[1], F_SETFL, O_NONBLOCK ); @@ -1522,19 +1521,17 @@ void Profiler::RemoveCrashHandler() if( m_crashHandlerInstalled ) { auto prev = SetUnhandledExceptionFilter( (LPTOP_LEVEL_EXCEPTION_FILTER)m_prevHandler ); - if( prev != CrashFilter ) - SetUnhandledExceptionFilter( prev ); // A different exception filter was installed over ours => put it back + if( prev != CrashFilter ) SetUnhandledExceptionFilter( prev ); // A different exception filter was installed over ours => put it back } #endif #if defined __linux__ && !defined TRACY_NO_CRASH_HANDLER if( m_crashHandlerInstalled ) { - auto restore = [this]( int signum, struct sigaction* prev ) { + auto restore = [ this ]( int signum, struct sigaction* prev ) { struct sigaction old; sigaction( signum, prev, &old ); - if( old.sa_sigaction != CrashHandler ) - sigaction( signum, &old, nullptr ); // A different signal handler was installed over ours => put it back + if( old.sa_sigaction != CrashHandler ) sigaction( signum, &old, nullptr ); // A different signal handler was installed over ours => put it back }; restore( TRACY_CRASH_SIGNAL, &m_prevSignal.pwr ); restore( SIGILL, &m_prevSignal.ill ); @@ -3108,10 +3105,7 @@ char* Profiler::SafeCopyProlog( const char* data, size_t size ) assert( !m_inUse.exchange(true) ); #endif - if( size > m_safeSendBufferSize ) - { - buf = (char*)tracy_malloc( size ); - } + if( size > m_safeSendBufferSize ) buf = (char*)tracy_malloc( size ); #ifdef _WIN32 __try @@ -3128,15 +3122,13 @@ char* Profiler::SafeCopyProlog( const char* data, size_t size ) { size_t sendsize = size - offset; ssize_t result1, result2; - while( ( result1 = write( m_pipe[1], data + offset, sendsize ) ) < 0 && errno == EINTR ) - /* retry */; + while( ( result1 = write( m_pipe[1], data + offset, sendsize ) ) < 0 && errno == EINTR ) { /* retry */ } if( result1 < 0 ) { success = false; break; } - while( ( result2 = read( m_pipe[0], buf + offset, result1 ) ) < 0 && errno == EINTR ) - /* retry */; + while( ( result2 = read( m_pipe[0], buf + offset, result1 ) ) < 0 && errno == EINTR ) { /* retry */ } if( result2 != result1 ) { success = false; @@ -3146,8 +3138,7 @@ char* Profiler::SafeCopyProlog( const char* data, size_t size ) } #endif - if( success ) - return buf; + if( success ) return buf; SafeCopyEpilog( buf ); return nullptr; @@ -3155,8 +3146,7 @@ char* Profiler::SafeCopyProlog( const char* data, size_t size ) void Profiler::SafeCopyEpilog( char* buf ) { - if( buf != m_safeSendBuffer ) - tracy_free( buf ); + if( buf != m_safeSendBuffer ) tracy_free( buf ); #ifndef NDEBUG m_inUse.store( false ); @@ -4117,13 +4107,12 @@ void Profiler::HandleSymbolCodeQuery( uint64_t symbol, uint32_t size ) } else { - // 'symbol' may have come from a module that has since unloaded, perform a safe copy before sending - if( WithSafeCopy( (const char*)symbol, size, [this, symbol]( const char* buf, size_t size ) { + auto&& lambda = [ this, symbol ]( const char* buf, size_t size ) { SendLongString( symbol, buf, size, QueueType::SymbolCode ); - })) - return; - - AckSymbolCodeNotAvailable(); + }; + + // 'symbol' may have come from a module that has since unloaded, perform a safe copy before sending + if( !WithSafeCopy( (const char*)symbol, size, lambda ) ) AckSymbolCodeNotAvailable(); } } From e1554a13e045e37a7aa2bf7b489db1e477c95288 Mon Sep 17 00:00:00 2001 From: Joshua Kriegshauser Date: Wed, 2 Oct 2024 11:21:14 -0700 Subject: [PATCH 7/8] PR feedback --- public/client/TracyProfiler.cpp | 3 +-- public/client/TracyProfiler.hpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/public/client/TracyProfiler.cpp b/public/client/TracyProfiler.cpp index 20738ac2..ac1c03ad 100644 --- a/public/client/TracyProfiler.cpp +++ b/public/client/TracyProfiler.cpp @@ -1463,7 +1463,6 @@ Profiler::Profiler() m_userPort = atoi( userPort ); } - m_safeSendBufferSize = 65536; m_safeSendBuffer = (char*)tracy_malloc( m_safeSendBufferSize ); #ifndef _WIN32 @@ -1528,7 +1527,7 @@ void Profiler::RemoveCrashHandler() #if defined __linux__ && !defined TRACY_NO_CRASH_HANDLER if( m_crashHandlerInstalled ) { - auto restore = [ this ]( int signum, struct sigaction* prev ) { + auto restore = []( int signum, struct sigaction* prev ) { struct sigaction old; sigaction( signum, prev, &old ); if( old.sa_sigaction != CrashHandler ) sigaction( signum, &old, nullptr ); // A different signal handler was installed over ours => put it back diff --git a/public/client/TracyProfiler.hpp b/public/client/TracyProfiler.hpp index 2fbaf9b4..883ebd4f 100644 --- a/public/client/TracyProfiler.hpp +++ b/public/client/TracyProfiler.hpp @@ -1010,7 +1010,7 @@ private: std::atomic_bool m_inUse{ false }; #endif char* m_safeSendBuffer; - size_t m_safeSendBufferSize; + constexpr static size_t m_safeSendBufferSize = 65536; #if defined _WIN32 void* m_prevHandler; From 66edfaec424796a25aa8edf0231e7d72d9898f75 Mon Sep 17 00:00:00 2001 From: Joshua Kriegshauser Date: Wed, 2 Oct 2024 12:50:12 -0700 Subject: [PATCH 8/8] More PR feedback --- public/client/TracyProfiler.cpp | 8 +++++--- public/client/TracyProfiler.hpp | 1 - 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/public/client/TracyProfiler.cpp b/public/client/TracyProfiler.cpp index ac1c03ad..84c246f2 100644 --- a/public/client/TracyProfiler.cpp +++ b/public/client/TracyProfiler.cpp @@ -1390,6 +1390,8 @@ TRACY_API LuaZoneState& GetLuaZoneState() { return s_luaZoneState; } TRACY_API bool ProfilerAvailable() { return s_instance != nullptr; } TRACY_API bool ProfilerAllocatorAvailable() { return !RpThreadShutdown; } +constexpr static size_t SafeSendBufferSize = 65536; + Profiler::Profiler() : m_timeBegin( 0 ) , m_mainThread( detail::GetThreadHandleImpl() ) @@ -1463,7 +1465,7 @@ Profiler::Profiler() m_userPort = atoi( userPort ); } - m_safeSendBuffer = (char*)tracy_malloc( m_safeSendBufferSize ); + m_safeSendBuffer = (char*)tracy_malloc( SafeSendBufferSize ); #ifndef _WIN32 pipe(m_pipe); @@ -1471,7 +1473,7 @@ Profiler::Profiler() // FreeBSD/XNU don't have F_SETPIPE_SZ, so use the default m_pipeBufSize = 16384; # else - m_pipeBufSize = (int)(ptrdiff_t)m_safeSendBufferSize; + m_pipeBufSize = (int)(ptrdiff_t)SafeSendBufferSize; while( fcntl( m_pipe[0], F_SETPIPE_SZ, m_pipeBufSize ) < 0 && errno == EPERM ) m_pipeBufSize /= 2; // too big; reduce m_pipeBufSize = fcntl( m_pipe[0], F_GETPIPE_SZ ); # endif @@ -3104,7 +3106,7 @@ char* Profiler::SafeCopyProlog( const char* data, size_t size ) assert( !m_inUse.exchange(true) ); #endif - if( size > m_safeSendBufferSize ) buf = (char*)tracy_malloc( size ); + if( size > SafeSendBufferSize ) buf = (char*)tracy_malloc( size ); #ifdef _WIN32 __try diff --git a/public/client/TracyProfiler.hpp b/public/client/TracyProfiler.hpp index 883ebd4f..38dd90c6 100644 --- a/public/client/TracyProfiler.hpp +++ b/public/client/TracyProfiler.hpp @@ -1010,7 +1010,6 @@ private: std::atomic_bool m_inUse{ false }; #endif char* m_safeSendBuffer; - constexpr static size_t m_safeSendBufferSize = 65536; #if defined _WIN32 void* m_prevHandler;