diff --git a/client/TracyProfiler.cpp b/client/TracyProfiler.cpp index e5f08e61..21857910 100644 --- a/client/TracyProfiler.cpp +++ b/client/TracyProfiler.cpp @@ -357,7 +357,20 @@ LONG WINAPI CrashFilter( PEXCEPTION_POINTERS pExp ) return EXCEPTION_CONTINUE_SEARCH; } - Profiler::Message( "!!!CRASH!!!" ); + { + const auto thread = GetThreadHandle(); + Magic magic; + auto& token = s_token.ptr; + auto& tail = token->get_tail_index(); + auto item = token->enqueue_begin( magic ); + MemWrite( &item->hdr.type, QueueType::CrashReport ); + item->crashReport.time = Profiler::GetTime(); + item->crashReport.thread = thread; + item->crashReport.text = (uint64_t)s_crashText; + tail.store( magic + 1, std::memory_order_release ); + + s_profiler.SendCallstack( 60, thread ); + } HANDLE h = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 ); if( h == INVALID_HANDLE_VALUE ) return EXCEPTION_CONTINUE_SEARCH; diff --git a/common/TracyQueue.hpp b/common/TracyQueue.hpp index 927fa9ef..341e2ca8 100644 --- a/common/TracyQueue.hpp +++ b/common/TracyQueue.hpp @@ -17,6 +17,7 @@ enum class QueueType : uint8_t Terminate, KeepAlive, Crash, + CrashReport, ZoneBegin, ZoneBeginCallstack, ZoneEnd, @@ -235,6 +236,13 @@ struct QueueCallstackFrame uint32_t line; }; +struct QueueCrashReport +{ + int64_t time; + uint64_t thread; + uint64_t text; // ptr +}; + struct QueueHeader { union @@ -271,6 +279,7 @@ struct QueueItem QueueCallstackMemory callstackMemory; QueueCallstack callstack; QueueCallstackFrame callstackFrame; + QueueCrashReport crashReport; }; }; @@ -289,6 +298,7 @@ static const size_t QueueDataSize[] = { sizeof( QueueHeader ), // terminate sizeof( QueueHeader ), // keep alive sizeof( QueueHeader ), // crash + sizeof( QueueHeader ) + sizeof( QueueCrashReport ), sizeof( QueueHeader ) + sizeof( QueueZoneBegin ), sizeof( QueueHeader ) + sizeof( QueueZoneBegin ), // callstack sizeof( QueueHeader ) + sizeof( QueueZoneEnd ), diff --git a/server/TracyEvent.hpp b/server/TracyEvent.hpp index e38371e2..d2ba95c0 100644 --- a/server/TracyEvent.hpp +++ b/server/TracyEvent.hpp @@ -181,6 +181,17 @@ struct CallstackFrameTree enum { CallstackFrameTreeSize = sizeof( CallstackFrameTree ) }; + +struct CrashEvent +{ + uint64_t thread = 0; + int64_t time = 0; + uint64_t message = 0; + uint32_t callstack = 0; +}; + +enum { CrashEventSize = sizeof( CrashEvent ) }; + #pragma pack() diff --git a/server/TracyWorker.cpp b/server/TracyWorker.cpp index 598ec78e..939794d5 100644 --- a/server/TracyWorker.cpp +++ b/server/TracyWorker.cpp @@ -1929,6 +1929,9 @@ void Worker::Process( const QueueItem& ev ) case QueueType::Crash: m_crashed = true; break; + case QueueType::CrashReport: + ProcessCrashReport( ev.crashReport ); + break; default: assert( false ); break; @@ -2574,6 +2577,9 @@ void Worker::ProcessCallstack( const QueueCallstack& ev ) case NextCallstackType::Gpu: next.gpu->callstack = it->second; break; + case NextCallstackType::Crash: + m_data.m_crashEvent.callstack = it->second; + break; default: assert( false ); break; @@ -2610,6 +2616,19 @@ void Worker::ProcessCallstackFrame( const QueueCallstackFrame& ev ) m_pendingCustomStrings.erase( m_pendingCustomStrings.find( ev.file ) ); } +void Worker::ProcessCrashReport( const QueueCrashReport& ev ) +{ + CheckString( ev.text ); + + auto& next = m_nextCallstack[ev.thread]; + next.type = NextCallstackType::Crash; + + m_data.m_crashEvent.thread = ev.thread; + m_data.m_crashEvent.time = TscTime( ev.time ); + m_data.m_crashEvent.message = ev.text; + m_data.m_crashEvent.callstack = 0; +} + void Worker::MemAllocChanged( int64_t time ) { const auto val = (double)m_data.memory.usage; diff --git a/server/TracyWorker.hpp b/server/TracyWorker.hpp index 84580162..3de5c9d0 100644 --- a/server/TracyWorker.hpp +++ b/server/TracyWorker.hpp @@ -140,6 +140,8 @@ private: std::vector> m_zoneChildren; std::vector> m_gpuChildren; + + CrashEvent m_crashEvent; }; struct MbpsBlock @@ -154,7 +156,8 @@ private: enum class NextCallstackType { Zone, - Gpu + Gpu, + Crash }; struct NextCallstack @@ -297,6 +300,7 @@ private: tracy_force_inline void ProcessCallstackMemory( const QueueCallstackMemory& ev ); tracy_force_inline void ProcessCallstack( const QueueCallstack& ev ); tracy_force_inline void ProcessCallstackFrame( const QueueCallstackFrame& ev ); + tracy_force_inline void ProcessCrashReport( const QueueCrashReport& ev ); tracy_force_inline void ProcessZoneBeginImpl( ZoneEvent* zone, const QueueZoneBegin& ev ); tracy_force_inline void ProcessGpuZoneBeginImpl( GpuEvent* zone, const QueueGpuZoneBegin& ev );