문제

System.Diagnostics.StackTrace를 사용하여 스택 추적을 가져올 수 있지만 스레드를 일시 중단해야 합니다.Suspend 및 Resume 기능은 더 이상 사용되지 않으므로 더 나은 방법이 있을 것으로 기대합니다.

도움이 되었습니까?

해결책

에 따르면 간단히 말해서 C# 3.0, 이것은 서스펜션/이력서를 호출해도 괜찮은 몇 가지 상황 중 하나입니다.

다른 팁

지금까지 저를 위해 일한 것은 다음과 같습니다.

StackTrace GetStackTrace (Thread targetThread)
{
    StackTrace stackTrace = null;
    var ready = new ManualResetEventSlim();

    new Thread (() =>
    {
        // Backstop to release thread in case of deadlock:
        ready.Set();
        Thread.Sleep (200);
        try { targetThread.Resume(); } catch { }
    }).Start();

    ready.Wait();
    targetThread.Suspend();
    try { stackTrace = new StackTrace (targetThread, true); }
    catch { /* Deadlock */ }
    finally
    {
        try { targetThread.Resume(); }
        catch { stackTrace = null;  /* Deadlock */  }
    }

    return stackTrace;
}

교착 상태가 있으면 교착 상태가 자동으로 해제되고 널 추적을 되 찾습니다. (그런 다음 다시 전화 할 수 있습니다.)

며칠 동안 테스트를 마친 후에는 코어 i7 컴퓨터에서 교착 상태를 만들 수있었습니다. 그러나 CPU가 100%로 실행될 때 단일 코어 VM에서 교착 상태가 일반적입니다.

이것은 오래된 스레드이지만 제안 된 솔루션에 대해 경고하고 싶었습니다. Sustend and Resume 솔루션은 작동하지 않습니다. 제 코드에서 시퀀스 중단/스택 트레이스/이력서를 시도하는 데 교착 상태가 발생했습니다.

문제는 stacktrace 생성기가 runtimemethodhandle-> methodbase conversions를 실행한다는 것입니다. 이는 내부 MethodinFocache를 변경하여 잠금을 취합니다. 교착 상태는 내가 검사하고있는 실이 또한 반사하고 있었고 그 자물쇠를 잡고 있었기 때문에 발생했습니다.

스택 트레이스 생성자 내부에서 일시 중단/이력서 물건이 수행되지 않는 것은 유감입니다.이 문제는 쉽게 우회 할 수있었습니다.

내 의견에서 언급했듯이 제안된 솔루션에는 교착 상태가 발생할 가능성이 여전히 적습니다.아래에서 내 버전을 찾아보세요.

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();
    }
}
}

내 생각에는 ManualResetEventSlim "fallbackThreadReady"가 실제로 필요하지는 않지만 이 민감한 경우에 위험을 감수할 이유가 무엇입니까?

대상 스레드의 협력 없이이 작업을 수행하려면 (예 : 세마포어 또는 스레드가 스택 트레이스를 수행하는 동안 세마포어에서 차단하는 메소드를 호출하는 것과 같은 경우) 더 이상 사용되지 않은 API를 사용해야한다고 생각합니다.

가능한 대안은 사용입니다 com 기반 Icordebug .NET 디버거가 사용하는 인터페이스. MDBG 코드베이스는 다음을 시작할 수 있습니다.

이것은 과거에 지원되는 운영 인 것 같지만 불행히도 Microsoft는 다음과 같습니다. https://msdn.microsoft.com/en-us/library/t2k35tat(v=vs.110).aspx

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top