Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dump StackTrace for each thread running [duplicate]

In java it is possible to get a snapshot of the stacktraces of all running threads. This is done with java.lang.Thread.getAllStackTraces() (it returns Map<Thread,StackTraceElement[]>).

How can this be done with .net?

like image 954
Daniel Sperry Avatar asked Jan 13 '10 15:01

Daniel Sperry


People also ask

How can I print stack trace without exception?

Just use new Throwable(). printStackTrace() method and it will print complete stack trace from where a method is called, into the console.

Should StackTrace be logged?

Therefore, you should log a stacktrace if, and only if, and always if, the exception indicates a bug in the program. However, that does not always indicate that a method you write should catch and log the exception.

How do you print StackTrace in logs?

To print a stack trace to log you Should declare logger and method info(e. toString()) or log(Level.INFO, e. toString()). Logging is the process of writing log messages during the execution of a program to get error and warning messages as well as info messages.

What is exception StackTrace?

A trace of the method calls is called a stack trace. The stack trace listing provides a way to follow the call stack to the line number in the method where the exception occurs. The StackTrace property returns the frames of the call stack that originate at the location where the exception was thrown.


3 Answers

So I actually just had to figure out how to do this -- haven't used this solution extensively in production yet, but theres a relatively new library called ClrMd.

http://blogs.msdn.com/b/dougste/archive/2013/05/04/clrmd-net-crash-dump-and-live-process-inspection.aspx

Using it, I'm able to attach to my own process and get a stack trace for all live threads. Using this when a deadlock is detected before restarting our app like so:

var result = new Dictionary<int, string[]>();

var pid = Process.GetCurrentProcess().Id;

using (var dataTarget = DataTarget.AttachToProcess(pid, 5000, AttachFlag.Passive))
{
    ClrInfo runtimeInfo = dataTarget.ClrVersions[0];
    var runtime = runtimeInfo.CreateRuntime();

    foreach (var t in runtime.Threads)
    {
        result.Add(
            t.ManagedThreadId,
            t.StackTrace.Select(f =>
            {
                if (f.Method != null)
                {
                    return f.Method.Type.Name + "." + f.Method.Name;
                }

                return null;
            }).ToArray()
        );
    }
}

var json = JsonConvert.SerializeObject(result);

zip.AddEntry("_threads.json", json);

The really important thing to get that to work from the same process is AttachFlag.Passive

If you just do DataTarget.AttachToProcess(pid, 5000), it'll do an "invasive" attach which attempts to pause the process. This throws an exception when you try to attach to your own process, I'm assuming because you can't pause your application while trying to attach from your application or something like that.

like image 73
Joshua Evensen Avatar answered Oct 06 '22 21:10

Joshua Evensen


If you want to get stack traces of all the threads within managed code then you could try mdbg. Have a look at Managed Stack Explorer it does use mdbg and gets stacks of all the threads.

like image 28
Naveen Avatar answered Oct 06 '22 23:10

Naveen


If you want this for debugging purposes alone, the SOS extensions to WinDbg can give you this information.

The command to run is "*~e !clrstack".

Inside of a running C# program, there is no public way to enumerate managed threads or look them up by ID. Even if you could, getting a stack trace on a different thread would likely require it to be suspended, which has some risks of side effects (see why this is obsolete).

The other alternative is to enlist threads as they are known, and scan them at your leisure. This is probably only possible if you're explicitly creating thread objects rather than using the thread pool.

That said, it is also hard for me to see what purpose this approach would serve. If it is for debugging, there are far more powerful techniques that can be done in-memory or on mini-dumps. If it is for logging, then it might make sense to have logging calls contribute their own stacks.

like image 7
Mason of Words Avatar answered Oct 06 '22 21:10

Mason of Words