111 lines
4.2 KiB
C#
111 lines
4.2 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.Threading;
|
|
using Bloomberg.Client.Report;
|
|
using Bloomberg.Message.Entities;
|
|
using Bloomberg.Message.Writer;
|
|
|
|
namespace Bloomberg.Client.Crash
|
|
{
|
|
public class ThreadCallstack : Data
|
|
{
|
|
public Thread Thread {get; set;}
|
|
|
|
public ThreadCallstack(Thread thread, ReportType supportedTypes): base($"Callstack- 0x{thread.ManagedThreadId:X}", supportedTypes)
|
|
{
|
|
Thread = thread;
|
|
}
|
|
|
|
public override void GetTextData(ReportInterface report, AttributeWriter attributeWriter)
|
|
{
|
|
if (!Thread.IsAlive)
|
|
return;
|
|
|
|
#pragma warning disable 618
|
|
var stackTrace = new StackTrace(Thread, true);
|
|
#pragma warning restore 618
|
|
|
|
StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames)
|
|
if (stackFrames == null)
|
|
return;
|
|
|
|
// write call stack method names
|
|
foreach (StackFrame stackFrame in stackFrames)
|
|
{
|
|
var methodInfo = stackFrame.GetMethod();
|
|
if (methodInfo == null)
|
|
continue;
|
|
|
|
attributeWriter.WriteValue(
|
|
$"{methodInfo.ReflectedType.Assembly.FullName}!{methodInfo.ReflectedType.FullName}.{methodInfo.Name} Line {stackFrame.GetFileLineNumber()} + 0x{(uint) stackFrame.GetILOffset():X} in {stackFrame.GetFileName()}");
|
|
}
|
|
}
|
|
}
|
|
|
|
public class ThreadsCallstack
|
|
{
|
|
public delegate bool RetrieveThreadCallstackDelegate(int threadId);
|
|
|
|
public RetrieveThreadCallstackDelegate RetrieveThreadCallstack { get; private set; }
|
|
|
|
public static ThreadsCallstack Instance { get; private set; }
|
|
|
|
/// <summary>
|
|
/// Private constructor called by Initialize
|
|
/// </summary>
|
|
private ThreadsCallstack(RetrieveThreadCallstackDelegate retrieveThreadCallstack, ReportType supportedTypes)
|
|
{
|
|
RetrieveThreadCallstack = retrieveThreadCallstack;
|
|
}
|
|
|
|
public static void Init(RetrieveThreadCallstackDelegate retrieveThreadCallstack, ReportType supportedTypes)
|
|
{
|
|
if (Instance == null)
|
|
Instance = new ThreadsCallstack(retrieveThreadCallstack, supportedTypes);
|
|
}
|
|
|
|
public void PrepareAdditionalCallstack()
|
|
{
|
|
// There is no way to enumerate thread in C#. The Process.Threads property give you a list of operating system threads, which are
|
|
// not managed thread. To get managed thread list, you need to do it from an external process.
|
|
// Short answer: keep track or thread yourself.
|
|
// Documentation:
|
|
// http://drdobbs.com/windows/184416664
|
|
// http://codequestion3.blogspot.com/2011/04/how-can-i-enumerate-all-managed-threads.html
|
|
// http://mse.codeplex.com/
|
|
|
|
/*
|
|
if (_threadCallstackList == null)
|
|
_threadCallstackList = new List<ThreadCallstack>();
|
|
|
|
// Reset
|
|
_threadCallstackList.ForEach(tcs => tcs.Enabled = false);
|
|
|
|
// Iterate
|
|
var process = Process.GetCurrentProcess();
|
|
foreach (ProcessThread thread in process.Threads)
|
|
{
|
|
// If we find the same thread and if it's still alive, skip the add
|
|
ProcessThread bkThread = thread;
|
|
ThreadCallstack threadCallstack = _threadCallstackList.Find(tcs => tcs.Thread == bkThread);
|
|
if (threadCallstack != null && threadCallstack.Thread.IsAlive)
|
|
{
|
|
threadCallstack.Enabled = true;
|
|
continue;
|
|
}
|
|
_threadCallstackList.Add(new ThreadCallstack(thread, _supportedTypes));
|
|
}
|
|
|
|
// Remove and unregister dead thread
|
|
foreach(ThreadCallstack threadCallstack in _threadCallstackList)
|
|
{
|
|
if (!threadCallstack.Enabled)
|
|
{
|
|
threadCallstack.UnregisterData();
|
|
_threadCallstackList.Remove(threadCallstack);
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
}
|