-
Notifications
You must be signed in to change notification settings - Fork 757
Description
When viewing CPU stacks from Linux EventPipe .nettrace traces (e.g., collected by one-collect), every thread stack shows a BROKEN frame between the thread/process root and the actual bottom frame (libc.so.6!__clone3), even though the stack is fully intact:
ROOT
+ Process32 dotnet (97856)
+ Thread (97868) CPU=2879ms
|+ BROKEN ← spurious
| + libc.so.6!__clone3
| + libc.so.6!start_thread
| + libcoreclr.so!CorUnix::CPalThread::ThreadEntry(void*)
| ...
Possible root cause:
ReasonableTopFrame() in TraceEventStacks.cs determines whether the deepest frame of a call stack is a valid thread entry point. It only recognizes ntdll.dll (Windows) and ntoskrnl.exe (kernel processes) as valid thread roots. On Linux, thread stacks bottom out in libc.so.6!__clone3 (or __clone, __libc_start_main), which fails this check, so every Linux thread stack is unconditionally routed through the "broken stack" encoding.
Possible fix:
Add libc (matching libc.so.6, libc.so, etc.) as a recognized thread-root module in ReasonableTopFrame(), alongside ntdll.dll.
e.g. in
perfview/src/TraceEvent/TraceEventStacks.cs
Line 639 in 46f2cfa
| private bool ReasonableTopFrame(StackSourceCallStackIndex callStackIndex, ThreadIndex threadIndex) |
// On Linux, threads start from libc's clone/clone3 or __libc_start_main.
string fileName = moduleFile.Name;
if (string.Compare(fileName, "libc", StringComparison.OrdinalIgnoreCase) == 0 ||
fileName.StartsWith("libc.", StringComparison.OrdinalIgnoreCase))
{
m_goodTopModuleIndex = moduleFileIndex;
return true;
}