1

처리되지 않은 예외가 발생하면 (AppDomain.CurrentDomain.UnhandledException 및 TaskScheduler.UnobservedTaskException을 사용하여) 미니 덤프를 생성하는 프로세스가 있습니다. 덤프는 처리되지 않은 예외 처리기에서 제대로 작동하지만 관찰되지 않은 작업 예외 처리기에서 호출 될 때 AccessViolationException을 생성합니다 (아래 예제 코드 참조).UnBservedTaskException 내부에 미니 덤프를 생성하면 AccessViolationException이 발생합니다.

MSDN 및 StackOverflow에서 읽은 바로는 두 코드 경로의 주요 차이점은 후자가 finalizer 스레드에서 발생하고 스레드 상태 또는 아마도 보안으로 인해이 작업이 성공하지 못하는 것으로 추측됩니다. .

관찰되지 않은 스레드 예외 상황에서 미니 덤프 작업이 실패하는 이유를 설명하는 정보 나 링크가 있습니까? 나는 단순히 노력하고있는 것이 불가능하다는 것을 받아 들여서 기쁩니다. 그러나 그 사실을 확인하고 이유를 알고 싶습니다.

아래의 코드는 내에서 처리되지 않은 예외를 트리거하여 내 문제를 보여줍니다. 관찰되지 않은 스레드 예외를 트리거하도록 가비지 콜렉션을 강요합니다. MiniDumpWriteDump 호출은 AccessViolationException을 생성합니다.

using System; 
using System.IO; 
using System.Runtime.ConstrainedExecution; 
using System.Runtime.ExceptionServices; 
using System.Runtime.InteropServices; 
using System.Security; 
using System.Threading; 
using System.Threading.Tasks; 

namespace ExceptionTest 
{ 
    public class ClassThatThrows 
    { 
     public void Throw() 
     { 
      var t = new Task(() => 
      { 
       Console.WriteLine("Throwing..."); 
       throw new NullReferenceException(); 
      }); 

      t.Start(); 
     } 
    } 

    public class Program 
    { 
     public static void Main(string[] args) 
     { 
      TaskScheduler.UnobservedTaskException += HandleUnobservedTaskException; 

      var test = new ClassThatThrows(); 
      test.Throw(); 

      Thread.Sleep(1000); 

      GC.Collect(); 
      GC.WaitForPendingFinalizers(); 

      Console.ReadLine(); 
     } 

     [HandleProcessCorruptedStateExceptions] 
     [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] 
     [SecurityCritical] 
     private static void HandleUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e) 
     { 
      WriteMiniDump(); 
     } 

     private static void WriteMiniDump() 
     { 
      var miniDumpFilePath = GetMiniDumpFilePath(); 

      using (var fileStream = new FileStream(miniDumpFilePath, FileMode.Create, FileAccess.Write, FileShare.None)) 
      { 
       MiniDumpExceptionInformation exceptionInfo; 
       exceptionInfo.ThreadId = GetCurrentWin32ThreadId(); 
       exceptionInfo.ClientPointers = false; 
       exceptionInfo.ExceptionPointers = Marshal.GetExceptionPointers(); 

       var currentProcess = GetCurrentProcess(); 
       var currentProcessId = GetCurrentProcessId(); 

       var safeFileHandle = fileStream.SafeFileHandle; 
       MiniDumpWriteDump(currentProcess, currentProcessId, safeFileHandle.DangerousGetHandle(), 0x00000000, ref exceptionInfo, IntPtr.Zero, IntPtr.Zero); 
      } 
     } 

     protected static string GetMiniDumpFilePath() 
     { 
      var timestamp = DateTime.Now.ToString("yyyyMMddTHHmmss"); 
      var fileName = string.Format("MiniDump.{0}.mdmp", timestamp); 
      return Path.Combine(Path.GetTempPath(), fileName); 
     } 

     [DllImport("Kernel32", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)] 
     public static extern uint GetCurrentWin32ThreadId(); 

     [DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] 
     public static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, IntPtr hFile, uint dumpType, ref MiniDumpExceptionInformation expParam, IntPtr userStreamParam, IntPtr callbackParam); 

     [DllImport("kernel32.dll", EntryPoint = "GetCurrentProcess", ExactSpelling = true)] 
     public static extern IntPtr GetCurrentProcess(); 

     [DllImport("kernel32.dll", EntryPoint = "GetCurrentProcessId", ExactSpelling = true)] 
     public static extern uint GetCurrentProcessId(); 

     [StructLayout(LayoutKind.Sequential, Pack = 4)] 
     public struct MiniDumpExceptionInformation 
     { 
      public uint ThreadId; 
      public IntPtr ExceptionPointers; 
      [MarshalAs(UnmanagedType.Bool)] 
      public bool ClientPointers; 
     } 
    } 
} 

감사

+0

'IntPtr'이 전달되는 것을 고정하려고 했습니까? –

+0

재현이 없으며 명백한 오류가 없습니다. Windows, dbghelp.dll 및 .NET 버전은 질문에 문서화되어야합니다. 내가 권장 할 수있는 것은 GC.KeepAlive (e.Exception);를 이벤트 핸들러에 장거리로 추가하는 것이다. 환경 문제를 찾으십시오. 또한 관리되지 않는 디버깅 인 Microsoft Symbol 서버를 활성화하고 폭탄이 나타날 때 표시되는 스택 추적을 게시하십시오. –

답변

0

은 내 집 컴퓨터에서 Yuval 교수의 제안을 구현하는 시도하고 즉시 나 직장에서 원래 컴퓨터에 중 Dbghelp.dll의 버전을 고려하게 문제를 재현 할 수 있습니다.

최신 Windows 8.1 SDK의 dbghelp.dll을 실행 파일 폴더에 넣은 후에 문제가 없어져서 dbghelp.dll이 최신이 아닌 dbghelp.dll에서 비난의 손가락을 가리킬 수 있고 mini를 만드는 데있어 애매한 C# 문제가 아닌 것을 지적 할 수 있습니다 finalizer 스레드에서 덤프합니다.

참조를 위해 dbghelp.dll 6.1.7601.17514가 문제를 나타내며 dbghelp.dll 6.3.9600.17029가 문제를 해결하는 것으로 확인되었습니다. 예외로부터의 호출 스택 (많은 것을 보여주지는 않지만)은 다음과 같습니다 :

ntdll.dll!NtWaitForSingleObject() 
KernelBase.dll!WaitForSingleObjectEx() 
msvcr110_clr0400.dll!__C_specific_handler() 
ntdll.dll!RtlpExecuteHandlerForException() 
ntdll.dll!RtlDispatchException() 
ntdll.dll!KiUserExceptionDispatch() 
dbghelp.dll!MiniDumpWriteDump() 
[Managed to Native Transition] 
    ExceptionTest.exe!ExceptionTest.Program.WriteMiniDump() Line 66 C# 
ExceptionTest.exe!ExceptionTest.Program.HandleUnobservedTaskException(object sender, System.Threading.Tasks.UnobservedTaskExceptionEventArgs e) Line 48 C# 
mscorlib.dll!System.Threading.Tasks.TaskScheduler.PublishUnobservedTaskException(object sender, System.Threading.Tasks.UnobservedTaskExceptionEventArgs ueea) 
mscorlib.dll!System.Threading.Tasks.TaskExceptionHolder.Finalize() 
관련 문제