public DbgEngDataReader(int pid, AttachFlag flags, uint msecTimeout) { IDebugClient client = CreateIDebugClient(); CreateClient(client); DEBUG_ATTACH attach = flags == AttachFlag.Invasive ? DEBUG_ATTACH.DEFAULT : DEBUG_ATTACH.NONINVASIVE; int hr = _control.AddEngineOptions(DEBUG_ENGOPT.INITIAL_BREAK); if (hr == 0) { hr = client.AttachProcess(0, (uint)pid, attach); } if (hr == 0) { hr = _control.WaitForEvent(0, msecTimeout); } if (hr == 1) { throw new TimeoutException("Break in did not occur within the allotted timeout."); } if (hr != 0) { if ((uint)hr == 0xd00000bb) { throw new InvalidOperationException("Mismatched architecture between this process and the target process."); } throw new ClrDiagnosticsException($"Could not attach to pid {pid:X}, HRESULT: 0x{hr:x8}", ClrDiagnosticsExceptionKind.DebuggerError, hr); } }
public DbgEngDataReader(int pid, AttachFlag flags, uint msecTimeout) { IDebugClient client = CreateIDebugClient(); CreateClient(client); DEBUG_ATTACH attach = (flags == AttachFlag.Invasive) ? DEBUG_ATTACH.DEFAULT : DEBUG_ATTACH.NONINVASIVE; int hr = _control.AddEngineOptions(DEBUG_ENGOPT.INITIAL_BREAK); if (hr == 0) hr = client.AttachProcess(0, (uint)pid, attach); if (hr == 0) hr = _control.WaitForEvent(0, msecTimeout); if (hr == 1) { throw new TimeoutException("Break in did not occur within the allotted timeout."); } else if (hr != 0) { if ((uint)hr == 0xd00000bb) throw new InvalidOperationException("Mismatched architecture between this process and the target process."); throw new ClrDiagnosticsException(String.Format("Could not attach to pid {0:X}, HRESULT: 0x{1:x8}", pid, hr), ClrDiagnosticsException.HR.DebuggerError); } }
public DbgEngDataReader(int pid, AttachFlag flags, uint msecTimeout) { IDebugClient client = CreateIDebugClient(); CreateClient(client); DEBUG_ATTACH attach = (flags == AttachFlag.Invasive) ? DEBUG_ATTACH.DEFAULT : DEBUG_ATTACH.NONINVASIVE; int hr = m_control.AddEngineOptions(DEBUG_ENGOPT.INITIAL_BREAK); if (hr == 0) { hr = client.AttachProcess(0, (uint)pid, attach); } if (hr == 0) { hr = m_control.WaitForEvent(0, msecTimeout); } if (hr == 1) { throw new TimeoutException("Break in did not occur within the allotted timeout."); } else if (hr != 0) { throw new ClrDiagnosticsException(String.Format("Could not attach to pid {0:X}, HRESULT: 0x{1:x8}", pid, hr), ClrDiagnosticsException.HR.DebuggerError); } }
public static string GetThreadDump(int pid, AttachFlag mode) { using (StringWriter writer = new StringWriter()) { try { using (var dataTarget = DataTarget.AttachToProcess(pid, 5000, mode)) { writer.WriteLine(dataTarget.ClrVersions.First().Version); var runtime = dataTarget.ClrVersions.First().CreateRuntime(); foreach (var domain in runtime.AppDomains) { writer.WriteLine("Domain " + domain.Name); } writer.WriteLine(); foreach (var t in runtime.Threads) { if (!t.IsAlive) { continue; } if (t.StackTrace.Count == 0) { continue; } writer.WriteLine("Thread " + t.ManagedThreadId + ": "); int loop_count = 0; foreach (var frame in t.EnumerateStackTrace()) { writer.WriteLine("\t" + frame.StackPointer.ToString("x16") + " " + frame.ToString()); loop_count++; if (loop_count > 200) { writer.WriteLine("\t[CORRUPTED]"); break; } } writer.WriteLine(); } } return(writer.ToString()); } catch { // This is mostly to catch the "invalid architecture" error. // Any error that happens we want to ignore and return what we have. return(writer.ToString()); } } }
public static DataTarget LoadOrAttach(string target, AttachFlag attachFlag, uint msecTimeout) { if (File.Exists(target)) { return(DataTarget.LoadCrashDump(target)); } Process process = null; Int32 processId; if (Int32.TryParse(target, out processId)) { process = Process.GetProcessById(processId); } else { var processes = Process.GetProcesses(); var found = new List <Process>(); // TODO: Access denied workaround foreach (var process1 in processes) { if (process1.ProcessName.StartsWith(target)) { found.Add(process1); } } if (found.Count > 1) { throw new ProcessNotFoundException("Multiple processes match the specified name."); } if (found.Count == 0) { throw new ProcessNotFoundException("No process matching the specified name can be found. Try elevating the command prompt."); } process = found[0]; } if (process == null) { throw new ProcessNotFoundException("No process matching the specified name can be found. Try elevating the command prompt."); } //Console.WriteLine($"Using {process.MainModule.FileName}"); return(DataTarget.AttachToProcess(process.Id, msecTimeout, attachFlag)); }
/// <summary> /// Attaches to a live process. /// </summary> /// <param name="pid">The process ID of the process to attach to.</param> /// <param name="msecTimeout">Timeout in milliseconds.</param> /// <param name="attachFlag">The type of attach requested for the target process.</param> /// <returns>A DataTarget instance.</returns> public static DataTarget AttachToProcess(int pid, uint msecTimeout, AttachFlag attachFlag) { IDebugClient client = null; IDataReader reader; if (attachFlag == AttachFlag.Passive) { #if NET45 reader = new LiveDataReader(pid, false); #else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { reader = new LiveDataReader(pid, false); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { reader = new Linux.LinuxLiveDataReader((uint)pid); } else { throw new NotSupportedException("Passive attach is not supported on OSX.s"); } #endif } else { #if !NET45 if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { throw new PlatformNotSupportedException("Currently only AttachFlag.Passive is supported for AttachToProcess"); } #endif DbgEngDataReader dbgeng = new DbgEngDataReader(pid, attachFlag, msecTimeout); reader = dbgeng; client = dbgeng.DebuggerInterface; } DataTargetImpl dataTarget = new DataTargetImpl(reader, client); #if !NET45 if (reader is Linux.LinuxLiveDataReader) { // TODO: discuss this design of // 1) add a method to IDataReader2 to return the list of module full path // 2) make DefaultSymbolLocator use that list as hint to load binaries dataTarget.SymbolLocator = new Linux.LinuxDefaultSymbolLocator(((Linux.LinuxLiveDataReader)reader).GetModulesFullPath()); } #endif return(dataTarget); }
/// <summary> /// Attaches to a live process. /// </summary> /// <param name="pid">The process ID of the process to attach to.</param> /// <param name="msecTimeout">Timeout in milliseconds.</param> /// <param name="attachFlag">The type of attach requested for the target process.</param> /// <returns>A DataTarget instance.</returns> public static DataTarget AttachToProcess(int pid, uint msecTimeout, AttachFlag attachFlag) { IDebugClient client = null; IDataReader reader; if (attachFlag == AttachFlag.Passive) { reader = new LiveDataReader(pid, false); } else { DbgEngDataReader dbgeng = new DbgEngDataReader(pid, attachFlag, msecTimeout); reader = dbgeng; client = dbgeng.DebuggerInterface; } DataTargetImpl dataTarget = new DataTargetImpl(reader, client); return(dataTarget); }
public static ClrMDSession AttachToProcess(string processName, uint millisecondsTimeout = 5000, AttachFlag attachFlag = AttachFlag.Invasive) { Process p = Process.GetProcessesByName(processName).FirstOrDefault(); if (p == null) { throw new ArgumentException("Process not found", "processName"); } return(AttachToProcess(p, millisecondsTimeout, attachFlag)); }
public static ClrMDSession AttachToProcess(Process p, uint millisecondsTimeout = 5000, AttachFlag attachFlag = AttachFlag.Invasive) { if (s_currentSession != null && s_lastProcessId == p.Id) { TestInvalidComObjectException(); return s_currentSession; } Detach(); DataTarget target = DataTarget.AttachToProcess(p.Id, millisecondsTimeout, attachFlag); string dacFile; try { dacFile = target.ClrVersions[0].TryGetDacLocation(); if (dacFile == null) throw new InvalidOperationException("Unable to find dac file. This may be caused by mismatched architecture between this process and the target process."); } catch { target.Dispose(); throw; } s_lastProcessId = p.Id; return new ClrMDSession(target, dacFile); }
static void Main(string[] args) { string process_set_id = "all"; AttachFlag mode = AttachFlag.Passive; int interval = 0; // command line parsing int i = 0; while (i < args.Length) { switch (args[i]) { case "-Passive": mode = AttachFlag.Passive; i++; continue; case "-NonInvasive": mode = AttachFlag.NonInvasive; i++; continue; case "-Invasive": mode = AttachFlag.Invasive; i++; continue; case "-Interval": i++; if (args.Length < i) { Console.WriteLine("Interval takes at least one argument"); return; } interval = Int32.Parse(args[i]); i++; continue; } process_set_id = args[i]; i++; } if (!process_sets.ContainsKey(process_set_id)) { Console.WriteLine("Must specify valid process set: all iis services"); return; } List <string> process_set = process_sets[process_set_id]; do { Stopwatch sw = new Stopwatch(); sw.Start(); using (TextWriter writer = new StreamWriter(File.Create("threads_" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".log"))) { writer.WriteLine(DateTime.Now.ToString()); foreach (var p in Process.GetProcesses()) { string filename = GetProcessFilename(p); if (process_set.Any(f => filename.EndsWith(f))) { writer.WriteLine(p.Id + " " + p.ProcessName + " " + filename); writer.WriteLine(GetThreadDump(p.Id, mode)); } } } sw.Stop(); // wait at least twice as long as it took to process // try to keep up with the defined interval Thread.Sleep(Math.Max(interval * 1000 - (int)sw.ElapsedMilliseconds, 2 * (int)sw.ElapsedMilliseconds)); } while (interval > 0); }
public static ClrMDSession AttachToProcess(string processName, uint millisecondsTimeout = 5000, AttachFlag attachFlag = AttachFlag.Invasive) { Process p = Process.GetProcessesByName(processName).FirstOrDefault(); if (p == null) throw new ArgumentException("Process not found", "processName"); return AttachToProcess(p, millisecondsTimeout, attachFlag); }
/// <summary> /// Attaches to a live process. /// </summary> /// <param name="pid">The process ID of the process to attach to.</param> /// <param name="msecTimeout">Timeout in milliseconds.</param> /// <param name="attachFlag">The type of attach requested for the target process.</param> /// <returns>A DataTarget instance.</returns> public static DataTarget AttachToProcess(int pid, uint msecTimeout, AttachFlag attachFlag) { Microsoft.Diagnostics.Runtime.Interop.IDebugClient client = null; IDataReader reader; if (attachFlag == AttachFlag.Passive) { reader = new LiveDataReader(pid); } else { var dbgeng = new DbgEngDataReader(pid, attachFlag, msecTimeout); reader = dbgeng; client = dbgeng.DebuggerInterface; } DataTargetImpl dataTarget = new DataTargetImpl(reader, client); return dataTarget; }
public static ClrMDSession AttachToProcess(Process p, uint millisecondsTimeout = 5000, AttachFlag attachFlag = AttachFlag.Invasive) { if (s_currentSession != null && s_lastProcessId == p.Id) { TestInvalidComObjectException(); return(s_currentSession); } Detach(); DataTarget target = DataTarget.AttachToProcess(p.Id, millisecondsTimeout, attachFlag); s_lastProcessId = p.Id; return(new ClrMDSession(target, null)); }
public ThreadDumpCollector(uint attachTimeoutInMillis, AttachFlag mode) { AttachTimeoutInMillis = attachTimeoutInMillis; Mode = mode; }
/// <summary> /// Initializes a new instance of the <see cref="DebugSession"/> class. /// </summary> /// <param name="processId">The process identifier.</param> /// <param name="milliSeconds">The milli seconds.</param> /// <param name="flag">The flag.</param> public DebugSession(int processId, uint milliSeconds, AttachFlag flag) : this() { AttachedTarget = DataTarget.AttachToProcess(processId, milliSeconds, flag); Initialize(); }
public static ClrMDSession AttachToProcess(int pid, uint millisecondsTimeout = 5000, AttachFlag attachFlag = AttachFlag.Invasive) { Process p = Process.GetProcessById(pid); if (p == null) { throw new ArgumentException("Process not found", "pid"); } return(AttachToProcess(p, millisecondsTimeout, attachFlag)); }
public static ClrMDSession AttachToProcess(Process p, uint millisecondsTimeout = 5000, AttachFlag attachFlag = AttachFlag.Invasive) { if (s_currentSession != null && s_lastProcessId == p.Id) { TestInvalidComObjectException(); return(s_currentSession); } Detach(); DataTarget target = DataTarget.AttachToProcess(p.Id, millisecondsTimeout, attachFlag); string dacFile; try { dacFile = target.ClrVersions[0].TryGetDacLocation(); if (dacFile == null) { throw new InvalidOperationException("Unable to find dac file. This may be caused by mismatched architecture between this process and the target process."); } } catch { target.Dispose(); throw; } s_lastProcessId = p.Id; return(new ClrMDSession(target, dacFile)); }
public static ClrMDSession AttachToProcess(int pid, uint millisecondsTimeout = 5000, AttachFlag attachFlag = AttachFlag.Invasive) { Process p = Process.GetProcessById(pid); if (p == null) throw new ArgumentException("Process not found", "pid"); return AttachToProcess(p, millisecondsTimeout, attachFlag); }