Beispiel #1
0
        /// <summary>Creates a textual description of the deadlock.</summary>
        /// <param name="currentChain">The deadlock cycle.</param>
        /// <param name="locksHeldByThreads">The table containing what locks are held by each thread holding locks.</param>
        /// <returns>The description of the deadlock.</returns>
        private static string CreateDeadlockDescription(
            CycleComponentNode currentChain,
            Dictionary <Thread, List <MonitorState> > locksHeldByThreads)
        {
            StringBuilder desc = new StringBuilder();

            for (CycleComponentNode node = currentChain; node != null; node = node.Next)
            {
                desc.AppendFormat("Thread {0} waiting on {1} ({2:X}) while holding ",
                                  node.Thread.ManagedThreadId, node.MonitorState.MonitorObject.ToString(),
                                  RuntimeHelpers.GetHashCode(node.MonitorState.MonitorObject));

                bool needsComma = false;

                foreach (MonitorState ms in locksHeldByThreads[node.Thread])
                {
                    if (needsComma)
                    {
                        desc.Append(", ");
                    }

                    desc.AppendFormat("{0} ({1:X})", ms.MonitorObject.ToString(),
                                      RuntimeHelpers.GetHashCode(ms.MonitorObject));

                    needsComma = true;
                }

                desc.AppendLine();
            }

            return(desc.ToString());
        }
Beispiel #2
0
 public bool ContainsThread(Thread t)
 {
     for (CycleComponentNode node = this; node != null; node = node.Next)
     {
         if (node.Thread == t)
         {
             return(true);
         }
     }
     return(false);
 }
Beispiel #3
0
        /// <summary>Creates a textual description of the deadlock.</summary>
        /// <param name="currentChain">The deadlock cycle.</param>
        /// <param name="locksHeldByThreads">The table containing what locks are held by each thread holding locks.</param>
        /// <returns>The description of the deadlock.</returns>
        private static string CreateDeadlockDescription(
            MonitorState competedState,
            CycleComponentNode currentChain,
            Dictionary <Thread, List <MonitorState> > locksHeldByThreads)
        {
            StringBuilder desc = new StringBuilder();

            for (CycleComponentNode node = currentChain; node != null; node = node.Next)
            {
                desc.AppendFormat("\r\nThread {0} waiting on: {1} ({2:X})\r\nCalling from:\r\n{3}\nwhile holding:\r\n",
                                  node.Thread.ManagedThreadId, node.MonitorState.MonitorObject.ToString(),
                                  RuntimeHelpers.GetHashCode(node.MonitorState.MonitorObject),
                                  node.MonitorState.traces[node.Thread]);

                foreach (MonitorState ms in locksHeldByThreads[node.Thread])
                {
                    desc.AppendFormat("{0} ({1:X})\r\n{2}", ms.MonitorObject.ToString(),
                                      RuntimeHelpers.GetHashCode(ms.MonitorObject), ms.traces[node.Thread]);
                }

                desc.AppendLine();
            }
            return(desc.ToString());
        }
Beispiel #4
0
 public CycleComponentNode(Thread thread, MonitorState ms, CycleComponentNode next)
 {
     Thread = thread;
     MonitorState = ms;
     Next = next;
 }
Beispiel #5
0
        /// <summary>Creates a textual description of the deadlock.</summary>
        /// <param name="currentChain">The deadlock cycle.</param>
        /// <param name="locksHeldByThreads">The table containing what locks are held by each thread holding locks.</param>
        /// <returns>The description of the deadlock.</returns>
        private static string CreateDeadlockDescription(
            MonitorState competedState,
            CycleComponentNode currentChain,
            Dictionary<Thread, List<MonitorState>> locksHeldByThreads)
        {
            StringBuilder desc = new StringBuilder();
            for (CycleComponentNode node = currentChain; node != null; node = node.Next)
            {
                desc.AppendFormat("\r\nThread {0} waiting on: {1} ({2:X})\r\nCalling from:\r\n{3}\nwhile holding:\r\n",
                    node.Thread.ManagedThreadId, node.MonitorState.MonitorObject.ToString(),
                    RuntimeHelpers.GetHashCode(node.MonitorState.MonitorObject),
                    node.MonitorState.traces[node.Thread]);

                foreach (MonitorState ms in locksHeldByThreads[node.Thread])
                    desc.AppendFormat("{0} ({1:X})\r\n{2}", ms.MonitorObject.ToString(),
                        RuntimeHelpers.GetHashCode(ms.MonitorObject), ms.traces[node.Thread]);

                desc.AppendLine();
            }
            return desc.ToString();
        }
        /// <summary>Creates a textual description of the deadlock.</summary>
        /// <param name="currentChain">The deadlock cycle.</param>
        /// <param name="locksHeldByThreads">The table containing what locks are held by each thread holding locks.</param>
        /// <returns>The description of the deadlock.</returns>
        private static string CreateDeadlockDescription(
            CycleComponentNode currentChain,
            Dictionary<Thread, List<MonitorState>> locksHeldByThreads)
        {
            StringBuilder desc = new StringBuilder();

            for (CycleComponentNode node = currentChain; node != null; node = node.Next)
            {
                desc.AppendFormat("Thread {0} waiting on {1} ({2:X}) while holding ",
                    node.Thread.ManagedThreadId, node.MonitorState.MonitorObject.ToString(),
                    RuntimeHelpers.GetHashCode(node.MonitorState.MonitorObject));

                bool needsComma = false;

                foreach (MonitorState ms in locksHeldByThreads[node.Thread])
                {
                    if (needsComma) desc.Append(", ");

                    desc.AppendFormat("{0} ({1:X})", ms.MonitorObject.ToString(),
                        RuntimeHelpers.GetHashCode(ms.MonitorObject));

                    needsComma = true;
                }

                desc.AppendLine();
            }

            return desc.ToString();
        }
Beispiel #7
0
 public CycleComponentNode(Thread thread, MonitorState ms, CycleComponentNode next)
 {
     Thread       = thread;
     MonitorState = ms;
     Next         = next;
 }
Beispiel #8
0
        /// <summary>Throws an exception if a deadlock would be caused by the current thread waiting on the specified lock.</summary>
        /// <param name="targetMs">The target lock data.</param>
        private static void ThrowIfDeadlockDetected(MonitorState targetMs)
        {
            // If no thread is holding the target lock, then this won't deadlock...
            if (targetMs.OwningThread == null)
            {
                return;
            }

            // For the deadlock detection algorithm, we need to know what locks are
            // currently held by which threads as well as which threads are waiting on
            // which locks. We already have this information, but we need it in a tabular
            // form for easier use and better perf.
            Dictionary <Thread, List <MonitorState> > locksHeldByThreads;
            Dictionary <MonitorState, List <Thread> > threadsWaitingOnLocks;

            CreateThreadAndLockTables(out locksHeldByThreads, out threadsWaitingOnLocks);

            // As we iterate over the wait graph, we'll need to store the list of threads still left to examine
            Queue <CycleComponentNode> threadsToFollow = new Queue <CycleComponentNode>(locksHeldByThreads.Count);

            // But rather than just storing the thread, we also store the threads in the cycle that got us to this thread.
            // The top of the stack is the actual thread to be examined.
            threadsToFollow.Enqueue(new CycleComponentNode(Thread.CurrentThread, targetMs, null));

            while (threadsToFollow.Count > 0)
            {
                // Get the next thread to examine
                CycleComponentNode currentChain  = threadsToFollow.Dequeue();
                Thread             currentThread = currentChain.Thread;

                // If this thread doesn't hold any locks, no point in examining it
                List <MonitorState> locksHeldByThread;
                if (!locksHeldByThreads.TryGetValue(currentThread, out locksHeldByThread))
                {
                    continue;
                }

                // For each lock it does hold, add to the thread examination list all threads
                // waiting on it.  And for each, see if it completes a cycle that results in
                // a deadlock.
                foreach (MonitorState ms in locksHeldByThread)
                {
                    List <Thread> nextThreads;
                    if (!threadsWaitingOnLocks.TryGetValue(ms, out nextThreads))
                    {
                        continue;
                    }
                    foreach (Thread nextThread in nextThreads)
                    {
                        // If any thread waiting on this lock is in the current stack,
                        // it's completng a cycle... deadlock!
                        if (currentChain.ContainsThread(nextThread))
                        {
                            throw new SynchronizationLockException(
                                      CreateDeadlockDescription(targetMs, currentChain, locksHeldByThreads));
                        }

                        // Clone the stack of threads in the possible cycle and add this to the top,
                        // then queue the stack for examination.
                        threadsToFollow.Enqueue(new CycleComponentNode(nextThread, ms, currentChain));
                    }
                }
            }
        }