From a5ff604c10b7e91733b1e8ffde59b5328ee95eb5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Mar 2026 19:54:38 +0000 Subject: [PATCH 1/2] Initial plan From f78a0a9ec5d2558de68b170df22594547a772651 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Mar 2026 19:59:08 +0000 Subject: [PATCH 2/2] Fix spurious BROKEN frame at top of Linux thread stacks in CPU Stacks viewer Co-authored-by: brianrob <6210322+brianrob@users.noreply.github.com> --- src/TraceEvent/TraceEventStacks.cs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/TraceEvent/TraceEventStacks.cs b/src/TraceEvent/TraceEventStacks.cs index 77a4986a0..f92c41bfc 100644 --- a/src/TraceEvent/TraceEventStacks.cs +++ b/src/TraceEvent/TraceEventStacks.cs @@ -662,6 +662,17 @@ private bool ReasonableTopFrame(StackSourceCallStackIndex callStackIndex, Thread return true; } + // On Linux, threads start from libc's __clone3, __clone, or __libc_start_main. + // Match libc.so.6, libc.so, libc-2.31.so, etc. + string moduleFileName = moduleFile.Name; + if (string.Compare(moduleFileName, "libc", StringComparison.OrdinalIgnoreCase) == 0 || + moduleFileName.StartsWith("libc.", StringComparison.OrdinalIgnoreCase) || + moduleFileName.StartsWith("libc-", StringComparison.OrdinalIgnoreCase)) + { + m_goodTopModuleIndex = moduleFileIndex; + return true; + } + // The special processes 4 (System) and 0 (Kernel) can stay in the kernel without being broken. if (moduleFile.FilePath.EndsWith("ntoskrnl.exe", StringComparison.OrdinalIgnoreCase)) { @@ -873,7 +884,13 @@ public StackSourceCallStackIndex GetCallStack(CallStackIndex callStackIndex, Sta var bangIdx = frameName.IndexOf('!'); if (0 < bangIdx) { - if (!(5 <= bangIdx && string.Compare(frameName, bangIdx - 5, "ntdll", 0, 5, StringComparison.OrdinalIgnoreCase) == 0)) + // Allow ntdll (Windows) and libc (Linux: libc.so.6, libc-2.31.so, etc.) as valid thread roots. + bool isNtdll = 5 <= bangIdx && string.Compare(frameName, bangIdx - 5, "ntdll", 0, 5, StringComparison.OrdinalIgnoreCase) == 0; + // Match libc, libc.so, libc.so.6, libc-2.31.so, but not libcrypto etc. + bool isLibc = 4 <= bangIdx && + string.Compare(frameName, 0, "libc", 0, 4, StringComparison.OrdinalIgnoreCase) == 0 && + (bangIdx == 4 || frameName[4] == '.' || frameName[4] == '-'); + if (!isNtdll && !isLibc) { var brokenFrame = m_Interner.FrameIntern("BROKEN", m_emptyModuleIdx); callerIdx = m_Interner.CallStackIntern(brokenFrame, callerIdx);