private void FillFaultingThreadAndModuleInformation(CommandExecutionContext context) { UnifiedStackTraces stackTrace = new UnifiedStackTraces(_dbgEngTarget.DebuggerInterface, context); _triageInformation.TotalThreadCount = (int)stackTrace.NumThreads; _triageInformation.ManagedThreadCount = stackTrace.Threads.Count(t => t.IsManagedThread); LastEventInformation lastEventInformation = _dbgEngTarget.GetLastEventInformation(); if (lastEventInformation == null) { return; } ThreadInformation faultingThread = stackTrace.Threads.SingleOrDefault(t => t.OSThreadId == lastEventInformation.OSThreadId); if (faultingThread == null) { return; } _triageInformation.FaultingThreadOSID = faultingThread.OSThreadId; _triageInformation.IsFaultingThreadManaged = faultingThread.IsManagedThread; _triageInformation.EventDescription = lastEventInformation.EventDescription; if (lastEventInformation.ExceptionRecord.HasValue) { _triageInformation.ExceptionCode = lastEventInformation.ExceptionRecord.Value.ExceptionCode; } if (faultingThread.IsManagedThread && faultingThread.ManagedThread.CurrentException != null) { _triageInformation.ManagedExceptionType = faultingThread.ManagedThread.CurrentException.Type.Name; } var frames = stackTrace.GetStackTrace(faultingThread.Index); UnifiedStackFrame faultingFrame = frames.FirstOrDefault(f => f.Module != null && !WellKnownMicrosoftModules.Contains(f.Module)); if (faultingFrame != null) { _triageInformation.FaultingModule = faultingFrame.Module; _triageInformation.FaultingMethod = faultingFrame.Method; } if (ShowFaultingStack) { context.WriteLine("Faulting call stack:"); stackTrace.PrintStackTrace(context, frames); } }
public override bool Generate(CommandExecutionContext context) { var target = context.NativeDbgEngTarget; var unifiedStackTraces = new UnifiedStackTraces(target.DebuggerInterface, context); var blockingObjectsStrategy = new DumpFileBlockingObjectsStrategy(context.Runtime, unifiedStackTraces, target); foreach (var thread in unifiedStackTraces.Threads) { // This function is created lazily because we don't need the managed // code state for each thread. Func <bool> checkManagedCodeStateForThisThread = () => unifiedStackTraces.GetStackTrace(thread.EngineThreadId) .Any(f => f.Type == UnifiedStackFrameType.Managed); var threadWithBlockingInfo = blockingObjectsStrategy.GetThreadWithBlockingObjects(thread); var threadInfo = new ThreadInfo { ManagedThreadId = threadWithBlockingInfo.ManagedThreadId, OSThreadId = threadWithBlockingInfo.OSThreadId, IsRunningManagedCode = checkManagedCodeStateForThisThread }; foreach (var blockingObject in threadWithBlockingInfo.BlockingObjects) { var lockInfo = new LockInfo { Reason = blockingObject.Reason.ToString() }; if (blockingObject.Type == UnifiedBlockingType.ClrBlockingObject) { lockInfo.Object = blockingObject.ManagedObjectAddress; lockInfo.ManagedObjectType = context.Heap.GetObjectType(lockInfo.Object)?.Name; } else { lockInfo.Object = blockingObject.Handle; lockInfo.OSObjectName = blockingObject.KernelObjectName; } lockInfo.OwnerThreadOSIds.AddRange(blockingObject.OwnerOSThreadIds); threadInfo.Locks.Add(lockInfo); } Threads.Add(threadInfo); RecommendFinalizerThreadBlocked(context); RecommendDeadlockedThreads(); } return(Threads.Any()); }
public DumpFileBlockingObjectsStrategy(ClrRuntime runtime, UnifiedStackTraces unifiedStackTraces, DataTarget dataTarget) : base(runtime, unifiedStackTraces, dataTarget) { if (_dataTarget != null) { try { _handles = runtime.DataTarget.DataReader.EnumerateHandles().ToList(); } catch (ClrDiagnosticsException) { // The dump file probably doesn't contain the handle stream. } } }
public override bool Generate(CommandExecutionContext context) { var managedThreadNames = GetManagedThreadNames(context.Heap); var target = context.NativeDbgEngTarget; IDebugSystemObjects3 sysObjects = (IDebugSystemObjects3)target.DebuggerInterface; sysObjects.GetCurrentProcessUpTime(out _processUpTimeInSeconds); var debugAdvanced = (IDebugAdvanced2)target.DebuggerInterface; var stackTraces = new UnifiedStackTraces(target.DebuggerInterface, context); foreach (var thread in stackTraces.Threads) { var stackTrace = stackTraces.GetStackTrace(thread.Index); var threadInfo = new ThreadInfo { EngineThreadId = thread.EngineThreadId, OSThreadId = thread.OSThreadId, ManagedThreadId = thread.ManagedThread?.ManagedThreadId ?? -1, SpecialDescription = thread.ManagedThread?.SpecialDescription() }; string threadName; if (managedThreadNames.TryGetValue(threadInfo.ManagedThreadId, out threadName)) { threadInfo.ThreadName = threadName; } threadInfo.Fill(debugAdvanced); foreach (var frame in stackTrace) { threadInfo.StackFrames.Add(new StackFrame { Module = frame.Module, Method = frame.Method, SourceFileName = frame.SourceFileName, SourceLineNumber = frame.SourceLineNumber }); } Threads.Add(threadInfo); } RecommendFinalizerThreadHighCPU(context); RecommendHighNumberOfThreads(); return(true); }
public void Execute(CommandExecutionContext context) { if (OSThreadId == 0) { OSThreadId = context.CurrentThread.OSThreadId; } context.WriteLine("{0,-10} {1,-20} {2}", "Type", "IP", "Function"); using (var target = context.CreateTemporaryDbgEngTarget()) { var stackTracer = new UnifiedStackTraces(target.DebuggerInterface, context); stackTracer.PrintStackTrace(context, (from thr in stackTracer.Threads where thr.OSThreadId == OSThreadId select thr.Index).Single()); } }
public BlockingObjectsStrategy( ClrRuntime runtime, UnifiedStackTraces unifiedStackTraces = null, DataTarget dataTarget = null) { _runtime = runtime; _unifiedStackTraces = unifiedStackTraces; _dataTarget = dataTarget; if (_dataTarget != null) { if (_dataTarget.Architecture == Architecture.X86) { _stackWalker = new StackWalkerStrategy_x86(_runtime); } _dataReader = _dataTarget.DataReader; _debugClient = _dataTarget.DebuggerInterface; } }
private void FillFaultingThreadAndModuleInformation(CommandExecutionContext context) { UnifiedStackTraces stackTrace = new UnifiedStackTraces(_dbgEngTarget.DebuggerInterface, context); _triageInformation.TotalThreadCount = (int)stackTrace.NumThreads; _triageInformation.ManagedThreadCount = stackTrace.Threads.Count(t => t.IsManagedThread); LastEventInformation lastEventInformation = _dbgEngTarget.GetLastEventInformation(); if (lastEventInformation == null) return; ThreadInformation faultingThread = stackTrace.Threads.SingleOrDefault(t => t.OSThreadId == lastEventInformation.OSThreadId); if (faultingThread == null) return; _triageInformation.FaultingThreadOSID = faultingThread.OSThreadId; _triageInformation.IsFaultingThreadManaged = faultingThread.IsManagedThread; _triageInformation.EventDescription = lastEventInformation.EventDescription; if (lastEventInformation.ExceptionRecord.HasValue) { _triageInformation.ExceptionCode = lastEventInformation.ExceptionRecord.Value.ExceptionCode; } if (faultingThread.IsManagedThread && faultingThread.ManagedThread.CurrentException != null) { _triageInformation.ManagedExceptionType = faultingThread.ManagedThread.CurrentException.Type.Name; } var frames = stackTrace.GetStackTrace(faultingThread.Index); UnifiedStackFrame faultingFrame = frames.FirstOrDefault(f => f.Module != null && !WellKnownMicrosoftModules.Contains(f.Module)); if (faultingFrame != null) { _triageInformation.FaultingModule = faultingFrame.Module; _triageInformation.FaultingMethod = faultingFrame.Method; } if (ShowFaultingStack) { context.WriteLine("Faulting call stack:"); stackTrace.PrintStackTrace(context, frames); } }
private void SetStrategy() { if (_context.TargetType == TargetType.DumpFile || _context.TargetType == TargetType.DumpFileNoHeap) { _temporaryDbgEngTarget = _context.CreateTemporaryDbgEngTarget(); _unifiedStackTraces = new UnifiedStackTraces(_temporaryDbgEngTarget.DebuggerInterface, _context); _blockingObjectsStrategy = new DumpFileBlockingObjectsStrategy(_context.Runtime, _unifiedStackTraces, _temporaryDbgEngTarget); _threads.AddRange(_unifiedStackTraces.Threads.Select(ti => _blockingObjectsStrategy.GetThreadWithBlockingObjects(ti))); } else { _blockingObjectsStrategy = new LiveProcessBlockingObjectsStrategy(_context.Runtime); // Currently, we are only enumerating the managed threads because we don't have // an alternative source of information for threads in live processes. In the future, // we can consider using System.Diagnostics or some other means of enumerating threads // in live processes. _threads.AddRange(_context.Runtime.Threads.Select(thr => _blockingObjectsStrategy.GetThreadWithBlockingObjects(thr))); } }
public void Execute(CommandExecutionContext context) { _context = context; if (IncludeNativeThreads) { using (var target = context.CreateTemporaryDbgEngTarget()) { var tracer = new UnifiedStackTraces(target.DebuggerInterface, context); context.WriteLine("Stack tree for {0} threads:", tracer.NumThreads); var allStacks = from thread in tracer.Threads let frames = from frame in tracer.GetStackTrace(thread.Index) where frame.Type != UnifiedStackFrameType.Special select frame.DisplayString select new ThreadAndStack { ManagedThreadId = thread.IsManagedThread ? thread.ManagedThread.ManagedThreadId : 0, OSThreadId = thread.OSThreadId, Stack = frames.Reverse() }; ProcessStacks(allStacks); } } else { context.WriteLine("Stack tree for {0} threads:", context.Runtime.Threads.Count); var allStacks = from thread in context.Runtime.Threads let frames = from frame in thread.StackTrace where frame.Kind == ClrStackFrameType.ManagedMethod select frame.DisplayString select new ThreadAndStack { ManagedThreadId = thread.ManagedThreadId, Stack = frames.Reverse() }; ProcessStacks(allStacks); } }
public override bool Generate(CommandExecutionContext context) { var target = context.NativeDbgEngTarget; var lastEvent = target.GetLastEventInformation(); if (lastEvent == null) { return(false); } var stackTraces = new UnifiedStackTraces(target.DebuggerInterface, context); var threadWithException = stackTraces.Threads.SingleOrDefault(t => t.OSThreadId == lastEvent.OSThreadId); if (threadWithException == null) { return(false); } Exception = new ExceptionInfo { ExceptionCode = lastEvent.ExceptionRecord?.ExceptionCode ?? 0 }; if (Exception.ExceptionCode == 0) { return(false); } OSThreadId = threadWithException.OSThreadId; ManagedThreadId = threadWithException.ManagedThread?.ManagedThreadId ?? 0; // Note that we want the thread's stack from the exception context, // and not from wherever it is right now. Exception.StackFrames = stackTraces.GetStackTraceFromStoredEvent() .Where(f => f.Type != UnifiedStackFrameType.Special) .Select(f => f.DisplayString) .ToList(); // Note that we might have an exception, but if it wasn't managed // then the Thread.CurrentException field will be null. var exception = threadWithException.ManagedThread?.CurrentException; if (exception == null) { return(true); } Exception.ExceptionType = exception.Type.Name; Exception.ExceptionMessage = exception.Message; exception = exception.Inner; var exceptionInfo = Exception; while (exception != null) { exceptionInfo.InnerException = new ExceptionInfo(); exceptionInfo = exceptionInfo.InnerException; exceptionInfo.ExceptionType = exception.Type.Name; exceptionInfo.ExceptionMessage = exception.Message; exceptionInfo.StackFrames = exception.StackTrace.Select(f => f.DisplayString).ToList(); exception = exception.Inner; } if (Exception != null) { Recommendations.Add(new UnhandledExceptionOccurred { Exception = Exception }); } return(true); }
private void SetStrategy() { if (_context.TargetType == TargetType.DumpFile || _context.TargetType == TargetType.DumpFile) { _temporaryDbgEngTarget = _context.CreateTemporaryDbgEngTarget(); _unifiedStackTraces = new UnifiedStackTraces(_temporaryDbgEngTarget.DebuggerInterface, _context); _blockingObjectsStrategy = new DumpFileBlockingObjectsStrategy(_context.Runtime, _unifiedStackTraces, _temporaryDbgEngTarget); _threads.AddRange(_unifiedStackTraces.Threads.Select(ti => _blockingObjectsStrategy.GetThreadWithBlockingObjects(ti))); } else { _blockingObjectsStrategy = new LiveProcessBlockingObjectsStrategy(_context.Runtime); // Currently, we are only enumerating the managed threads because we don't have // an alternative source of information for threads in live processes. In the future, // we can consider using System.Diagnostics or some other means of enumerating threads // in live processes. _threads.AddRange(_context.Runtime.Threads.Select(thr => _blockingObjectsStrategy.GetThreadWithBlockingObjects(thr))); } }