public void Dump(int pid, DumpType dumpType, string fileName, string dumpComment = null) { _pid = pid; _dumpType = dumpType; dumpComment = dumpComment ?? ("DumpWriter: " + _dumpType.ToString()); IntPtr hProcess = DumpNativeMethods.OpenProcess( ProcessAccessFlags.QueryInformation | ProcessAccessFlags.VirtualMemoryRead | ProcessAccessFlags.DuplicateHandle, false, (uint)_pid ); if (hProcess == IntPtr.Zero) { throw new ArgumentException(String.Format("Unable to open process {0}, error {x:8}", _pid, Marshal.GetLastWin32Error())); } FileStream dumpFileStream = new FileStream(fileName, FileMode.Create); var exceptionParam = new MINIDUMP_EXCEPTION_INFORMATION(); var userStreamParam = PrepareUserStream(dumpComment); var callbackParam = new MINIDUMP_CALLBACK_INFORMATION(); if (_dumpType == DumpType.FullMemoryExcludingSafeRegions || _dumpType == DumpType.MinimalWithFullCLRHeap) { callbackParam.CallbackRoutine = CallbackRoutine; } MINIDUMP_TYPE nativeDumpType = (_dumpType == DumpType.FullMemory || _dumpType == DumpType.FullMemoryExcludingSafeRegions) ? MINIDUMP_TYPE.MiniDumpWithFullMemory | MINIDUMP_TYPE.MiniDumpWithHandleData | MINIDUMP_TYPE.MiniDumpWithFullMemoryInfo : MINIDUMP_TYPE.MiniDumpWithHandleData | MINIDUMP_TYPE.MiniDumpWithFullMemoryInfo; bool success = DumpNativeMethods.MiniDumpWriteDump( hProcess, (uint)_pid, dumpFileStream.SafeFileHandle.DangerousGetHandle(), nativeDumpType, ref exceptionParam, ref userStreamParam, ref callbackParam ); if (!success) { throw new ApplicationException(String.Format("Error writing dump, error {0:x8}", Marshal.GetLastWin32Error())); } userStreamParam.Delete(); DumpNativeMethods.CloseHandle(hProcess); dumpFileStream.Close(); }
public void Dump(int pid, DumpType dumpType, string fileName, string dumpComment = null) { _pid = pid; _dumpType = dumpType; dumpComment = dumpComment ?? ("DumpWriter: " + _dumpType.ToString()); IntPtr hProcess = DumpNativeMethods.OpenProcess( ProcessAccessFlags.QueryInformation | ProcessAccessFlags.VirtualMemoryRead | ProcessAccessFlags.DuplicateHandle, false, (uint)_pid ); if (hProcess == IntPtr.Zero) throw new ArgumentException(String.Format("Unable to open process {0}, error {x:8}", _pid, Marshal.GetLastWin32Error())); FileStream dumpFileStream = new FileStream(fileName, FileMode.Create); var exceptionParam = new MINIDUMP_EXCEPTION_INFORMATION(); var userStreamParam = PrepareUserStream(dumpComment); var callbackParam = new MINIDUMP_CALLBACK_INFORMATION(); if (_dumpType == DumpType.FullMemoryExcludingSafeRegions || _dumpType == DumpType.MinimalWithFullCLRHeap) { callbackParam.CallbackRoutine = CallbackRoutine; } MINIDUMP_TYPE nativeDumpType = (_dumpType == DumpType.FullMemory || _dumpType == DumpType.FullMemoryExcludingSafeRegions) ? MINIDUMP_TYPE.MiniDumpWithFullMemory | MINIDUMP_TYPE.MiniDumpWithHandleData | MINIDUMP_TYPE.MiniDumpWithFullMemoryInfo : MINIDUMP_TYPE.MiniDumpWithHandleData | MINIDUMP_TYPE.MiniDumpWithFullMemoryInfo; bool success = DumpNativeMethods.MiniDumpWriteDump( hProcess, (uint)_pid, dumpFileStream.SafeFileHandle.DangerousGetHandle(), nativeDumpType, ref exceptionParam, ref userStreamParam, ref callbackParam ); if (!success) throw new ApplicationException(String.Format("Error writing dump, error {0:x8}", Marshal.GetLastWin32Error())); userStreamParam.Delete(); DumpNativeMethods.CloseHandle(hProcess); dumpFileStream.Close(); }
public void Dump(int pid, DumpType dumpType, string fileName, bool writeAsync = false, string dumpComment = null) { _pid = pid; _dumpType = dumpType; _spillSegmentsAsynchronously = writeAsync; dumpComment = dumpComment ?? ("DumpWriter: " + _dumpType.ToString()); IntPtr hProcess = DumpNativeMethods.OpenProcess( ProcessAccessFlags.QueryInformation | ProcessAccessFlags.VirtualMemoryRead | ProcessAccessFlags.DuplicateHandle, false, (uint)_pid ); if (hProcess == IntPtr.Zero) { throw new ArgumentException(String.Format("Unable to open process {0}, error {x:8}", _pid, Marshal.GetLastWin32Error())); } _dumpFileStream = new FileStream(fileName, FileMode.Create); var exceptionParam = new MINIDUMP_EXCEPTION_INFORMATION(); var userStreamParam = PrepareUserStream(dumpComment); var callbackParam = new MINIDUMP_CALLBACK_INFORMATION(); _needMemoryCallbacks = ( _dumpType == DumpType.FullMemoryExcludingSafeRegions || _dumpType == DumpType.MinimalWithFullCLRHeap ); if (_needMemoryCallbacks || _spillSegmentsAsynchronously) { callbackParam.CallbackRoutine = CallbackRoutine; } MINIDUMP_TYPE nativeDumpType = (_dumpType == DumpType.FullMemory || _dumpType == DumpType.FullMemoryExcludingSafeRegions) ? MINIDUMP_TYPE.MiniDumpWithFullMemory | MINIDUMP_TYPE.MiniDumpWithHandleData | MINIDUMP_TYPE.MiniDumpWithFullMemoryInfo : MINIDUMP_TYPE.MiniDumpWithHandleData | MINIDUMP_TYPE.MiniDumpWithFullMemoryInfo; Stopwatch sw = Stopwatch.StartNew(); bool success = DumpNativeMethods.MiniDumpWriteDump( hProcess, (uint)_pid, _dumpFileStream.SafeFileHandle.DangerousGetHandle(), nativeDumpType, ref exceptionParam, ref userStreamParam, ref callbackParam ); if (!success) { throw new ApplicationException(String.Format("Error writing dump, error {0:x8}", Marshal.GetLastWin32Error())); } _logger.WriteLine("Process was suspended for {0:N2}ms", sw.Elapsed.TotalMilliseconds); if (_spillSegmentsAsynchronously) { // We are asynchronously spilling dump segments to disk, need to wait // for this process to complete before returning to the caller. _segmentSpillingTask.Wait(); _logger.WriteLine( "Total dump writing time including async flush was {0:N2}ms", sw.Elapsed.TotalMilliseconds); } userStreamParam.Delete(); DumpNativeMethods.CloseHandle(hProcess); _dumpFileStream.Close(); }
public void Dump(int pid, DumpType dumpType, string fileName, bool writeAsync = false, string dumpComment = null) { _pid = pid; _dumpType = dumpType; _spillSegmentsAsynchronously = writeAsync; dumpComment = dumpComment ?? ("DumpWriter: " + _dumpType.ToString()); IntPtr hProcess = DumpNativeMethods.OpenProcess( ProcessAccessFlags.QueryInformation | ProcessAccessFlags.VirtualMemoryRead | ProcessAccessFlags.DuplicateHandle, false, (uint)_pid ); if (hProcess == IntPtr.Zero) throw new ArgumentException(String.Format("Unable to open process {0}, error {x:8}", _pid, Marshal.GetLastWin32Error())); _dumpFileStream = new FileStream(fileName, FileMode.Create); var exceptionParam = new MINIDUMP_EXCEPTION_INFORMATION(); var userStreamParam = PrepareUserStream(dumpComment); var callbackParam = new MINIDUMP_CALLBACK_INFORMATION(); _needMemoryCallbacks = ( _dumpType == DumpType.FullMemoryExcludingSafeRegions || _dumpType == DumpType.MinimalWithFullCLRHeap ); if (_needMemoryCallbacks || _spillSegmentsAsynchronously) { callbackParam.CallbackRoutine = CallbackRoutine; } MINIDUMP_TYPE nativeDumpType = (_dumpType == DumpType.FullMemory || _dumpType == DumpType.FullMemoryExcludingSafeRegions) ? MINIDUMP_TYPE.MiniDumpWithFullMemory | MINIDUMP_TYPE.MiniDumpWithHandleData | MINIDUMP_TYPE.MiniDumpWithFullMemoryInfo : MINIDUMP_TYPE.MiniDumpWithHandleData | MINIDUMP_TYPE.MiniDumpWithFullMemoryInfo; Stopwatch sw = Stopwatch.StartNew(); bool success = DumpNativeMethods.MiniDumpWriteDump( hProcess, (uint)_pid, _dumpFileStream.SafeFileHandle.DangerousGetHandle(), nativeDumpType, ref exceptionParam, ref userStreamParam, ref callbackParam ); if (!success) throw new ApplicationException(String.Format("Error writing dump, error {0:x8}", Marshal.GetLastWin32Error())); _logger.WriteLine("Process was suspended for {0:N2}ms", sw.Elapsed.TotalMilliseconds); if (_spillSegmentsAsynchronously) { // We are asynchronously spilling dump segments to disk, need to wait // for this process to complete before returning to the caller. _segmentSpillingTask.Wait(); _logger.WriteLine( "Total dump writing time including async flush was {0:N2}ms", sw.Elapsed.TotalMilliseconds); } userStreamParam.Delete(); DumpNativeMethods.CloseHandle(hProcess); _dumpFileStream.Close(); }
public void DumpOnException(uint threadId, EXCEPTION_RECORD ev) { if (ev.ExceptionCode == BREAKPOINT_CODE) { return; } if (ev.ExceptionCode == CLRDBG_NOTIFICATION_EXCEPTION_CODE) { // based on https://social.msdn.microsoft.com/Forums/vstudio/en-US/bca092d4-d2b5-49ef-8bbc-cbce2c67aa89/net-40-firstchance-exception-0x04242420?forum=clr // it's a "notification exception" and can be safely ignored return; } if (ev.ExceptionCode == CTRL_C_EXCEPTION_CODE) { // we will also ignore CTRL+C events return; } // print information about the exception (decode it) ClrException managedException = null; foreach (var clrver in target.ClrVersions) { var runtime = clrver.CreateRuntime(); var thr = runtime.Threads.FirstOrDefault(t => t.OSThreadId == threadId); if (thr != null) { managedException = thr.CurrentException; break; } } var exceptionInfo = string.Format("{0:X}.{1} (\"{2}\")", ev.ExceptionCode, managedException != null ? managedException.Type.Name : "Native", managedException != null ? managedException.Message : "N/A"); PrintTrace("Exception: " + exceptionInfo); if (rgxFilter.IsMatch(exceptionInfo)) { byte[] threadContext = new byte[Native.CONTEXT_SIZE]; target.DataReader.GetThreadContext(threadId, 0, Native.CONTEXT_SIZE, threadContext); IntPtr pev = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(EXCEPTION_RECORD))); Marshal.StructureToPtr(new EXCEPTION_RECORD{ ExceptionAddress = ev.ExceptionAddress, ExceptionFlags = ev.ExceptionFlags, ExceptionCode = ev.ExceptionCode, ExceptionRecord = IntPtr.Zero, NumberParameters = ev.NumberParameters, ExceptionInformation = ev.ExceptionInformation }, pev, false); var excpointers = new EXCEPTION_POINTERS { ExceptionRecord = pev, ContextRecord = threadContext }; IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(excpointers)); Marshal.StructureToPtr(excpointers, ptr, false); var excinfo = new MINIDUMP_EXCEPTION_INFORMATION() { ThreadId = threadId, ClientPointers = false, ExceptionPointers = ptr }; var pexcinfo = Marshal.AllocHGlobal(Marshal.SizeOf(excinfo)); Marshal.StructureToPtr(excinfo, pexcinfo, false); MakeActualDump(pexcinfo); Marshal.FreeHGlobal(pev); Marshal.FreeHGlobal(pexcinfo); Marshal.FreeHGlobal(ptr); } }