An additional flag to parallel stacks to include runtime stacks to pstacks command...
authorIgor Bagdamyan <37334640+En3Tho@users.noreply.github.com>
Tue, 5 Dec 2023 21:27:40 +0000 (00:27 +0300)
committerGitHub <noreply@github.com>
Tue, 5 Dec 2023 21:27:40 +0000 (13:27 -0800)
This adds "-r" flag to include Runtime stacks to pstacks output
It will still ignore the frame if it's method is null. It's just a
matter of checking for both Runtime and Managed kinds
Sometimes it might be useful to have those too, for example like in
https://github.com/dotnet/diagnostics/issues/4418 when it is still
useful to know which threads are in locked state

src/Microsoft.Diagnostics.ExtensionCommands/ParallelStacks.Runtime/ParallelStack.cs
src/Microsoft.Diagnostics.ExtensionCommands/ParallelStacksCommand.cs

index f2653bb8dfd41373ef44309b3be4550134ca619d..c3287f0cdcf000c098b854faa7f66317602fa1af 100644 (file)
@@ -11,7 +11,7 @@ namespace ParallelStacks.Runtime
 {
     public class ParallelStack
     {
-        public static ParallelStack Build(ClrRuntime runtime)
+        public static ParallelStack Build(ClrRuntime runtime, bool includeRuntimeStacks)
         {
             ParallelStack ps = new();
             List<ClrStackFrame> stackFrames = new(64);
@@ -20,7 +20,11 @@ namespace ParallelStacks.Runtime
                 stackFrames.Clear();
                 foreach (ClrStackFrame stackFrame in thread.EnumerateStackTrace().Reverse())
                 {
-                    if ((stackFrame.Kind != ClrStackFrameKind.ManagedMethod) || (stackFrame.Method == null))
+                    bool shouldAdd =
+                        stackFrame.Kind == ClrStackFrameKind.ManagedMethod
+                            || (includeRuntimeStacks && stackFrame.Kind == ClrStackFrameKind.Runtime);
+
+                    if ((!shouldAdd) || (stackFrame.Method == null))
                     {
                         continue;
                     }
@@ -39,7 +43,7 @@ namespace ParallelStacks.Runtime
             return ps;
         }
 
-        public static ParallelStack Build(string dumpFile, string dacFilePath)
+        public static ParallelStack Build(string dumpFile, string dacFilePath, bool includeRuntimeStacks)
         {
             DataTarget dataTarget = null;
             ParallelStack ps = null;
@@ -63,7 +67,7 @@ namespace ParallelStacks.Runtime
                     return null;
                 }
 
-                ps = ParallelStack.Build(runtime);
+                ps = ParallelStack.Build(runtime, includeRuntimeStacks);
             }
             finally
             {
@@ -73,7 +77,7 @@ namespace ParallelStacks.Runtime
             return ps;
         }
 
-        public static ParallelStack Build(int pid, string dacFilePath)
+        public static ParallelStack Build(int pid, string dacFilePath, bool includeRuntimeStacks)
         {
             DataTarget dataTarget = null;
             ParallelStack ps = null;
@@ -100,7 +104,7 @@ namespace ParallelStacks.Runtime
                     return null;
                 }
 
-                ps = ParallelStack.Build(runtime);
+                ps = ParallelStack.Build(runtime, includeRuntimeStacks);
             }
             finally
             {
index 3320f11d34e1ccb650bea082d789b50b16e093cb..0b9a987e4731a9a7e69179e49d4cacebd66c2387 100644 (file)
@@ -17,9 +17,12 @@ namespace Microsoft.Diagnostics.ExtensionCommands
         [Option(Name = "--allthreads", Aliases = new string[] { "-a" }, Help = "Displays all threads per group instead of at most 4 by default.")]
         public bool AllThreads { get; set; }
 
+        [Option(Name = "--runtime", Aliases = new string[] { "-r" }, Help = "Displays runtime stacks in addition to managed ones.")]
+        public bool IncludeRuntimeStacks { get; set; }
+
         public override void Invoke()
         {
-            ParallelStack ps = ParallelStack.Build(Runtime);
+            ParallelStack ps = ParallelStack.Build(Runtime, IncludeRuntimeStacks);
             if (ps == null)
             {
                 return;