public void Execute(CommandExecutionContext context) { _context = context; try { SetStrategy(); if (SpecificOSThreadId != 0) { UnifiedThread thread = SpecificThread; if (SpecificThread == null) { _context.WriteErrorLine("There is no thread with the id '{0}'.", SpecificOSThreadId); return; } DisplayChainForThread(thread, 0, new HashSet <uint>()); } else { _threads.ForEach(thread => DisplayChainForThread(thread, 0, new HashSet <uint>())); } } finally { _temporaryDbgEngTarget?.Dispose(); } }
private void DisplayThreadBlockingObjects(UnifiedThread unifiedThread, int depth, List <UnifiedBlockingObject> blockingObjects, HashSet <uint> visitedThreadIds) { foreach (var blockingObject in unifiedThread.BlockingObjects) { _context.Write("{0}| {1} {2}", new string(' ', (depth + 1) * 2), blockingObject.Reason, blockingObject.ReasonDescription); if (!String.IsNullOrEmpty(blockingObject.KernelObjectName)) { _context.Write( String.Format("{0:x16} {1} {2}", blockingObject.Handle, blockingObject.KernelObjectTypeName, blockingObject.KernelObjectName)); } if (blockingObject.Type == UnifiedBlockingType.ClrBlockingObject) { var type = _context.Heap.GetObjectType(blockingObject.ManagedObjectAddress); if (type != null && !String.IsNullOrEmpty(type.Name)) { _context.WriteLink( String.Format("{0:x16} {1}", blockingObject.ManagedObjectAddress, type.Name), String.Format("!do {0:x16}", blockingObject.ManagedObjectAddress)); } else { _context.Write("{0:x16}", blockingObject.ManagedObjectAddress); } } _context.WriteLine(); foreach (var owner in blockingObject.OwnerOSThreadIds) { var thread = _threads.SingleOrDefault(t => t.OSThreadId == owner); // We won't necessarily have that thread on our list because it might be // a thread in another process, e.g. for mutexes. if (thread != null) { DisplayChainForThread(thread, depth + 2, visitedThreadIds); } } } }
private void DisplayChainForThread(UnifiedThread unifiedThread, int depth, HashSet <uint> visitedThreadIds) { if (unifiedThread.IsManagedThread) { var command = String.Format("~ {0}; !mk", unifiedThread.ManagedThreadId); _context.WriteLink(String.Format("{0}+ OS Thread {1}", new string(' ', depth * 2), unifiedThread.OSThreadId), command); } else { _context.Write("+ OS Thread {0}", unifiedThread.OSThreadId); } _context.WriteLine(); if (visitedThreadIds.Contains(unifiedThread.OSThreadId)) { _context.WriteLine("{0}*** DEADLOCK!", new string(' ', depth * 2)); return; } visitedThreadIds.Add(unifiedThread.OSThreadId); DisplayThreadBlockingObjects(unifiedThread, depth, unifiedThread.BlockingObjects, visitedThreadIds); }
private void DisplayThreadBlockingObjects(UnifiedThread unifiedThread, int depth, List<UnifiedBlockingObject> blockingObjects, HashSet<uint> visitedThreadIds) { foreach (var blockingObject in unifiedThread.BlockingObjects) { _context.Write("{0}| {1} ", new string(' ', (depth + 1) * 2), blockingObject.Reason); if (!String.IsNullOrEmpty(blockingObject.KernelObjectName)) { _context.Write( String.Format("{0:x16} {1} {2}", blockingObject.Handle, blockingObject.KernelObjectTypeName, blockingObject.KernelObjectName)); } if (blockingObject.Type == UnifiedBlockingType.ClrBlockingObject) { var type = _context.Heap.GetObjectType(blockingObject.ManagedObjectAddress); if (type != null && !String.IsNullOrEmpty(type.Name)) { _context.WriteLink( String.Format("{0:x16} {1}", blockingObject.ManagedObjectAddress, type.Name), String.Format("!do {0:x16}", blockingObject.ManagedObjectAddress)); } else { _context.Write("{0:x16}", blockingObject.ManagedObjectAddress); } } _context.WriteLine(); foreach (var owner in blockingObject.OwnerOSThreadIds) { var thread = _threads.SingleOrDefault(t => t.OSThreadId == owner); // We won't necessarily have that thread on our list because it might be // a thread in another process, e.g. for mutexes. if (thread != null) DisplayChainForThread(thread, depth + 2, visitedThreadIds); } } }
private void DisplayChainForThread(UnifiedThread unifiedThread, int depth, HashSet<uint> visitedThreadIds) { if (unifiedThread.IsManagedThread) { var command = String.Format("~ {0}; !mk", unifiedThread.ManagedThreadId); _context.WriteLink(String.Format("{0}+ OS Thread {1}", new string(' ', depth * 2), unifiedThread.OSThreadId), command); } else { _context.Write("+ OS Thread {0}", unifiedThread.OSThreadId); } _context.WriteLine(); if (visitedThreadIds.Contains(unifiedThread.OSThreadId)) { _context.WriteLine("{0}*** DEADLOCK!", new string(' ', depth * 2)); return; } visitedThreadIds.Add(unifiedThread.OSThreadId); DisplayThreadBlockingObjects(unifiedThread, depth, unifiedThread.BlockingObjects, visitedThreadIds); }