From a25812bd5a46a0c7be441cb40de553a34762fd15 Mon Sep 17 00:00:00 2001 From: Simeon Andreev Date: Fri, 10 Jun 2022 17:36:11 +0200 Subject: [PATCH] Prevent endless loop in lock cycle detection #1510 This change prevents an endless loop in: ReentrantCycleDetectingLock.addAllLockIdsAfter() For reasons that are not yet clear, according to CycleDetectingLockFactory.locksOwnedByThread and ReentrantCycleDetectingLock.lockOwnerThread, a thread both owns a lock and waits on that same lock. This leads to an endless loop in the cycle detection. The change adds a workaround, forcing the cycle detection to exit if the above condition is met. --- core/src/com/google/inject/internal/CycleDetectingLock.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/src/com/google/inject/internal/CycleDetectingLock.java b/core/src/com/google/inject/internal/CycleDetectingLock.java index d767015548..a43627683b 100644 --- a/core/src/com/google/inject/internal/CycleDetectingLock.java +++ b/core/src/com/google/inject/internal/CycleDetectingLock.java @@ -255,6 +255,7 @@ private ListMultimap detectPotentialLocksCycle() { // in case locks cycle exists lock we're waiting for is part of it lockOwnerWaitingOn = addAllLockIdsAfter(threadOwnerThreadWaits, lockOwnerWaitingOn, potentialLocksCycle); + if (threadOwnerThreadWaits == currentThread) { // owner thread depends on current thread, cycle detected return potentialLocksCycle; @@ -293,6 +294,10 @@ private ReentrantCycleDetectingLock addAllLockIdsAfter( Preconditions.checkState( found, "Internal error: We can not find locks that created a cycle that we detected"); ReentrantCycleDetectingLock unownedLock = lockThreadIsWaitingOn.get(thread); + if (unownedLock == lock) { + // XXX: bandaid, how do we have a thread that owns a lock but also waits on that same lock? + return null; + } // If this thread is waiting for a lock add it to the cycle and return it if (unownedLock != null && unownedLock.lockFactory == this.lockFactory) { @SuppressWarnings("unchecked")