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?
Just use new Throwable(). printStackTrace() method and it will print complete stack trace from where a method is called, into the console.
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.
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With