From 4c55b68b8a989097d1d5d10eeec56f5c74d0c3c4 Mon Sep 17 00:00:00 2001 From: Radek Felcman Date: Wed, 15 Jan 2025 08:26:18 +0100 Subject: [PATCH] DeadLock diagnostic fix (#2288) Fix for event when massive dumps, triggered by dead lock diagnostic, are produced. Before this fix the concurrency layers should continue to update structures (Maps, Sets) passed to dead lock diagnostic and these structures could be updated in time period between detected dead lock event and print to some log output. After this fix snapshots are produced. Signed-off-by: Radek Felcman --- .../internal/helper/ConcurrencyManager.java | 40 ++++++++++++------- .../internal/helper/ConcurrencyUtil.java | 20 +++++----- .../internal/helper/WriteLockManager.java | 10 ++--- .../type/CacheKeyToThreadRelationships.java | 4 +- 4 files changed, 42 insertions(+), 32 deletions(-) diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/ConcurrencyManager.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/ConcurrencyManager.java index 18fdf3f63c0..ea4c8a0234d 100644 --- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/ConcurrencyManager.java +++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/ConcurrencyManager.java @@ -28,8 +28,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; import java.util.IdentityHashMap; import java.util.Iterator; import java.util.List; @@ -437,6 +435,13 @@ protected static Map getDeferredLockManagers() { return DEFERRED_LOCK_MANAGERS; } + /** + * Return snapshot of the deferred lock manager hashtable (thread - DeferredLockManager). + */ + protected static Map getDeferredLockManagersSnapshot() { + return Map.copyOf(DEFERRED_LOCK_MANAGERS); + } + /** * Init the deferred lock managers (thread - DeferredLockManager). */ @@ -870,6 +875,13 @@ protected static Map getReadLockManagers() { return READ_LOCK_MANAGERS; } + /** + * Return snapshot of the deferred lock manager hashtable (thread - DeferredLockManager). + */ + protected static Map getReadLockManagersSnapshot() { + return Map.copyOf(READ_LOCK_MANAGERS); + } + /** * Print the nested depth. */ @@ -971,33 +983,33 @@ public long getTotalNumberOfKeysReleasedForReadingBlewUpExceptionDueToCacheKeyHa } /** Getter for {@link #THREADS_TO_WAIT_ON_ACQUIRE} */ - public static Map getThreadsToWaitOnAcquire() { - return new HashMap<>(THREADS_TO_WAIT_ON_ACQUIRE); + public static Map getThreadsToWaitOnAcquireSnapshot() { + return Map.copyOf(THREADS_TO_WAIT_ON_ACQUIRE); } /** Getter for {@link #THREADS_TO_WAIT_ON_ACQUIRE_NAME_OF_METHOD_CREATING_TRACE} */ - public static Map getThreadsToWaitOnAcquireMethodName() { - return new HashMap<>(THREADS_TO_WAIT_ON_ACQUIRE_NAME_OF_METHOD_CREATING_TRACE); + public static Map getThreadsToWaitOnAcquireMethodNameSnapshot() { + return Map.copyOf(THREADS_TO_WAIT_ON_ACQUIRE_NAME_OF_METHOD_CREATING_TRACE); } /** Getter for {@link #THREADS_TO_WAIT_ON_ACQUIRE_READ_LOCK} */ - public static Map getThreadsToWaitOnAcquireReadLock() { - return THREADS_TO_WAIT_ON_ACQUIRE_READ_LOCK; + public static Map getThreadsToWaitOnAcquireReadLockSnapshot() { + return Map.copyOf(THREADS_TO_WAIT_ON_ACQUIRE_READ_LOCK); } /** Getter for {@link #THREADS_TO_WAIT_ON_ACQUIRE_READ_LOCK_NAME_OF_METHOD_CREATING_TRACE} */ - public static Map getThreadsToWaitOnAcquireReadLockMethodName() { - return THREADS_TO_WAIT_ON_ACQUIRE_READ_LOCK_NAME_OF_METHOD_CREATING_TRACE; + public static Map getThreadsToWaitOnAcquireReadLockMethodNameSnapshot() { + return Map.copyOf(THREADS_TO_WAIT_ON_ACQUIRE_READ_LOCK_NAME_OF_METHOD_CREATING_TRACE); } /** Getter for {@link #THREADS_WAITING_TO_RELEASE_DEFERRED_LOCKS} */ - public static Set getThreadsWaitingToReleaseDeferredLocks() { - return new HashSet<>(THREADS_WAITING_TO_RELEASE_DEFERRED_LOCKS); + public static Set getThreadsWaitingToReleaseDeferredLocksSnapshot() { + return Set.copyOf(THREADS_WAITING_TO_RELEASE_DEFERRED_LOCKS); } /** Getter for {@link #THREADS_WAITING_TO_RELEASE_DEFERRED_LOCKS_BUILD_OBJECT_COMPLETE_GOES_NOWHERE} */ - public static Map getThreadsWaitingToReleaseDeferredLocksJustification() { - return new HashMap<>(THREADS_WAITING_TO_RELEASE_DEFERRED_LOCKS_BUILD_OBJECT_COMPLETE_GOES_NOWHERE); + public static Map getThreadsWaitingToReleaseDeferredLocksJustificationSnapshot() { + return Map.copyOf(THREADS_WAITING_TO_RELEASE_DEFERRED_LOCKS_BUILD_OBJECT_COMPLETE_GOES_NOWHERE); } /** diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/ConcurrencyUtil.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/ConcurrencyUtil.java index 12a3633c868..c46e469d14e 100644 --- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/ConcurrencyUtil.java +++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/ConcurrencyUtil.java @@ -469,16 +469,16 @@ public void dumpConcurrencyManagerInformationIfAppropriate() { } // do the "MassiveDump" logging if enough time has passed since the previous massive dump logging - Map deferredLockManagers = ConcurrencyManager.getDeferredLockManagers(); - Map readLockManagersOriginal = ConcurrencyManager.getReadLockManagers(); - Map mapThreadToWaitOnAcquireOriginal = ConcurrencyManager.getThreadsToWaitOnAcquire(); - Map mapThreadToWaitOnAcquireMethodNameOriginal = ConcurrencyManager.getThreadsToWaitOnAcquireMethodName(); - Map mapThreadToWaitOnAcquireReadLockOriginal = ConcurrencyManager.getThreadsToWaitOnAcquireReadLock(); - Map mapThreadToWaitOnAcquireReadLockMethodNameOriginal = ConcurrencyManager.getThreadsToWaitOnAcquireReadLockMethodName(); - Map> mapThreadToWaitOnAcquireInsideWriteLockManagerOriginal = WriteLockManager.getThreadToFailToAcquireCacheKeys(); - Set setThreadWaitingToReleaseDeferredLocksOriginal = ConcurrencyManager.getThreadsWaitingToReleaseDeferredLocks(); - Map mapThreadsThatAreCurrentlyWaitingToReleaseDeferredLocksJustificationClone = ConcurrencyManager.getThreadsWaitingToReleaseDeferredLocksJustification(); - Map> mapThreadToObjectIdWithWriteLockManagerChangesOriginal = WriteLockManager.getMapWriteLockManagerThreadToObjectIdsWithChangeSet(); + Map deferredLockManagers = ConcurrencyManager.getDeferredLockManagersSnapshot(); + Map readLockManagersOriginal = ConcurrencyManager.getReadLockManagersSnapshot(); + Map mapThreadToWaitOnAcquireOriginal = ConcurrencyManager.getThreadsToWaitOnAcquireSnapshot(); + Map mapThreadToWaitOnAcquireMethodNameOriginal = ConcurrencyManager.getThreadsToWaitOnAcquireMethodNameSnapshot(); + Map mapThreadToWaitOnAcquireReadLockOriginal = ConcurrencyManager.getThreadsToWaitOnAcquireReadLockSnapshot(); + Map mapThreadToWaitOnAcquireReadLockMethodNameOriginal = ConcurrencyManager.getThreadsToWaitOnAcquireReadLockMethodNameSnapshot(); + Map> mapThreadToWaitOnAcquireInsideWriteLockManagerOriginal = WriteLockManager.getThreadToFailToAcquireCacheKeysSnapshot(); + Set setThreadWaitingToReleaseDeferredLocksOriginal = ConcurrencyManager.getThreadsWaitingToReleaseDeferredLocksSnapshot(); + Map mapThreadsThatAreCurrentlyWaitingToReleaseDeferredLocksJustificationClone = ConcurrencyManager.getThreadsWaitingToReleaseDeferredLocksJustificationSnapshot(); + Map> mapThreadToObjectIdWithWriteLockManagerChangesOriginal = WriteLockManager.getMapWriteLockManagerThreadToObjectIdsWithChangeSetSnapshot(); dumpConcurrencyManagerInformationStep01( deferredLockManagers, readLockManagersOriginal, diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/WriteLockManager.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/WriteLockManager.java index c6878106d0c..0580636e884 100644 --- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/WriteLockManager.java +++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/WriteLockManager.java @@ -49,8 +49,6 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; -import static java.util.Collections.unmodifiableMap; - /** * INTERNAL: *

@@ -654,13 +652,13 @@ protected CacheKey waitOnObjectLock(ClassDescriptor descriptor, Object primaryKe // Helper data structures to have tracebility about object ids with change sets and cache keys we are sturggling to acquire /** Getter for {@link #THREAD_TO_FAIL_TO_ACQUIRE_CACHE_KEYS} */ - public static Map> getThreadToFailToAcquireCacheKeys() { - return unmodifiableMap(THREAD_TO_FAIL_TO_ACQUIRE_CACHE_KEYS); + public static Map> getThreadToFailToAcquireCacheKeysSnapshot() { + return Map.copyOf(THREAD_TO_FAIL_TO_ACQUIRE_CACHE_KEYS); } /** Getter for {@link #MAP_WRITE_LOCK_MANAGER_THREAD_TO_OBJECT_IDS_WITH_CHANGE_SET} */ - public static Map> getMapWriteLockManagerThreadToObjectIdsWithChangeSet() { - return unmodifiableMap(MAP_WRITE_LOCK_MANAGER_THREAD_TO_OBJECT_IDS_WITH_CHANGE_SET); + public static Map> getMapWriteLockManagerThreadToObjectIdsWithChangeSetSnapshot() { + return Map.copyOf(MAP_WRITE_LOCK_MANAGER_THREAD_TO_OBJECT_IDS_WITH_CHANGE_SET); } /** diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/type/CacheKeyToThreadRelationships.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/type/CacheKeyToThreadRelationships.java index ca1e28da052..0eaae5fce43 100644 --- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/type/CacheKeyToThreadRelationships.java +++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/type/CacheKeyToThreadRelationships.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -62,7 +62,7 @@ public class CacheKeyToThreadRelationships { /** * These are threads that have registered themselves as waiting for the cache key. See - * {@link org.eclipse.persistence.internal.helper.ConcurrencyManager#getThreadsToWaitOnAcquire()} + * {@link org.eclipse.persistence.internal.helper.ConcurrencyManager#getThreadsToWaitOnAcquireSnapshot()} * * (acquire lock for writing or as deferred - the cache key must be found with number of readers 0). */