How to get non-current thread's stacktrace?

前端 未结 6 1714
别那么骄傲
别那么骄傲 2020-12-05 02:28

It is possible to get stacktrace using System.Diagnostics.StackTrace, but thread has to be suspended. Suspend and Resume function are obsolete, so I expect that better way e

6条回答
  •  旧巷少年郎
    2020-12-05 03:00

    As mentioned in my comment, the proposed solution above does still have a tiny probability for a deadlock. Please find my version below.

    private static StackTrace GetStackTrace(Thread targetThread) {
    using (ManualResetEvent fallbackThreadReady = new ManualResetEvent(false), exitedSafely = new ManualResetEvent(false)) {
        Thread fallbackThread = new Thread(delegate() {
            fallbackThreadReady.Set();
            while (!exitedSafely.WaitOne(200)) {
                try {
                    targetThread.Resume();
                } catch (Exception) {/*Whatever happens, do never stop to resume the target-thread regularly until the main-thread has exited safely.*/}
            }
        });
        fallbackThread.Name = "GetStackFallbackThread";
        try {
            fallbackThread.Start();
            fallbackThreadReady.WaitOne();
            //From here, you have about 200ms to get the stack-trace.
            targetThread.Suspend();
            StackTrace trace = null;
            try {
                trace = new StackTrace(targetThread, true);
            } catch (ThreadStateException) {
                //failed to get stack trace, since the fallback-thread resumed the thread
                //possible reasons:
                //1.) This thread was just too slow (not very likely)
                //2.) The deadlock ocurred and the fallbackThread rescued the situation.
                //In both cases just return null.
            }
            try {
                targetThread.Resume();
            } catch (ThreadStateException) {/*Thread is running again already*/}
            return trace;
        } finally {
            //Just signal the backup-thread to stop.
            exitedSafely.Set();
            //Join the thread to avoid disposing "exited safely" too early. And also make sure that no leftover threads are cluttering iis by accident.
            fallbackThread.Join();
        }
    }
    }
    

    I think, the ManualResetEventSlim "fallbackThreadReady" is not really necessary, but why risk anything in this delicate case?

提交回复
热议问题