From 4a6c75d8f8a11a5370c15cfb8d01fb54531e7ea9 Mon Sep 17 00:00:00 2001 From: Marcos Slomp Date: Wed, 17 Dec 2025 08:03:34 -0800 Subject: [PATCH] ensure all stackwalk requests are satisfied --- public/client/windows/TracyETW.cpp | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/public/client/windows/TracyETW.cpp b/public/client/windows/TracyETW.cpp index f71e42e9..510fc462 100644 --- a/public/client/windows/TracyETW.cpp +++ b/public/client/windows/TracyETW.cpp @@ -23,6 +23,7 @@ struct Session EVENT_TRACE_PROPERTIES properties = {}; CHAR name[64] = {}; CONTROLTRACE_ID handle = 0; + CLASSIC_EVENT_ID stackwalk[8] = {}; }; // ---- ETW Events ---------- @@ -213,6 +214,8 @@ static ULONG StopSession( Session& session ) return ETWError( status ); // once stopped, the session handle becomes invalid session.handle = 0; + for ( auto&& sw : session.stackwalk ) + sw = {}; return ERROR_SUCCESS; } @@ -289,11 +292,24 @@ static ULONG EnableStackWalk( Session& session, GUID EventGuid, UCHAR Opcode ) { if( !IsOS64Bit() ) return 0 /* ERROR_SUCCESS */; // TODO: return error instead? - CLASSIC_EVENT_ID stackId[1] = {}; - stackId[0].EventGuid = EventGuid; - stackId[0].Type = Opcode; - ULONG status = TraceSetInformation( session.handle, TraceStackTracingInfo, &stackId, sizeof( stackId ) ); - return ETWError( status ); + // TraceStackTracingInfo: Turns on stack trace collection for the specified kernel events + // for the specified logger. It also turns off stack tracing for + // all kernel events not on this list, regardless of prior status. + // NOTE: It'd be nice if we could rely on TraceQueryInformation(TraceStackTracingInfo) + // to retrieve the list of the active stack trace event ids, but even though MSDN says + // that it is possible, the query call returns ERROR_NOT_SUPPORTED... + // Instead, we keep our own array of active stack trace event ids in the session object. + for( auto&& sw : session.stackwalk ) + { + if ( !IsEqualGUID( sw.EventGuid, {} ) ) + continue; + sw.EventGuid = EventGuid; + sw.Type = Opcode; + size_t count = ( &sw - session.stackwalk ) + 1; + ULONG status = TraceSetInformation( session.handle, TraceStackTracingInfo, session.stackwalk, count * sizeof( CLASSIC_EVENT_ID ) ); + return ETWError( status ); + } + return 0 /* ERROR_SUCCESS */; // TODO: return error instead? } static ULONG SetCPUProfilingInterval(int microseconds)