JD2022-TU1/main/tools/extern/Bloomberg/Code/Clients/BloombergClientCSharp/Crash/ThreadsCallstack.cs

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);
}
}
*/
}
}
}