Community
Participate
Working Groups
It has been found that a deadlock occurs in checkReadLock when another thread has merge locks on the cache: It occurs as follows: Thread-1 -> issueSQLBeforeCompletion -> locks object A for later merge Thread-2 -> issueSQLBeforeCompletion -> attempts to lock object tree and cannot Thread-2 -> is notified and wakes up ->locks object B attempts to acquire lock Object A -> waits on Thread-1 Thread-1 -> mergeClonesAfterCompletion -> on merge of relationship attempts readlock on Object B -> deadlocks
Created attachment 123296 [details] Patch file and test cases By removing the readlock check when simply checking for existence of the cachekey then we can avoid the deadlock.
Diagnosis information: The symptoms appear in the following thread dump. These packages are TopLink but the same symptoms appear in the EclipseLink packages "WebContainer : 7" daemon prio=10 tid=0x0000000106cd05b0 nid=0xe82 in Object.wait() [0xfffffffe416f9000..0xfffffffe416ff628] at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:474) at oracle.toplink.internal.helper.ConcurrencyManager.acquire(ConcurrencyManager.java:76) - locked <0xfffffffeb3ad2248> (a oracle.toplink.internal.helper.ConcurrencyManager) at oracle.toplink.internal.identitymaps.CacheKey.acquire(CacheKey.java:81) at oracle.toplink.internal.identitymaps.IdentityMap.acquireLock(IdentityMap.java:85) at oracle.toplink.internal.identitymaps.IdentityMapManager.acquireLock(IdentityMapManager.java:101) at oracle.toplink.internal.sessions.IdentityMapAccessor.acquireLock(IdentityMapAccessor.java:68) at oracle.toplink.internal.helper.WriteLockManager.waitOnObjectLock(WriteLockManager.java:420) at oracle.toplink.internal.helper.WriteLockManager.acquireRequiredLocks(WriteLockManager.java:255) at oracle.toplink.publicinterface.UnitOfWork.commitToDatabase(UnitOfWork.java:1348) "WebContainer : 5" daemon prio=10 tid=0x0000000105b27960 nid=0x543 in Object.wait() [0xfffffffe33ef8000..0xfffffffe33eff6a8] at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:474) at oracle.toplink.internal.helper.ConcurrencyManager.acquireReadLock(ConcurrencyManager.java:179) - locked <0xfffffffe8d83c1b0> (a oracle.toplink.internal.helper.ConcurrencyManager) at oracle.toplink.internal.identitymaps.CacheKey.acquireReadLock(CacheKey.java:129) at oracle.toplink.internal.identitymaps.IdentityMapManager.getFromIdentityMap(IdentityMapManager.java:492) at oracle.toplink.internal.sessions.IdentityMapAccessor.getFromIdentityMap(IdentityMapAccessor.java:283) at oracle.toplink.internal.sessions.IdentityMapAccessor.getFromIdentityMap(IdentityMapAccessor.java:265) at oracle.toplink.publicinterface.UnitOfWork.getOriginalVersionOfObjectOrNull(UnitOfWork.java:2364) at oracle.toplink.internal.sessions.MergeManager.mergeChangesOfWorkingCopyIntoOriginal(MergeManager.java:575) at oracle.toplink.internal.sessions.MergeManager.mergeChanges(MergeManager.java:223)
Created attachment 123368 [details] updated patch Patch contains a small typo update
Patch checked in to 1.1X stream
Created attachment 123912 [details] transition to deferred locks This update includes a new patch that transitions active locks to deferred locks if a readlock can not be acquired. This prevents a deadlock while still maintaining read integrity. This update requires that the non-starving components of the merge locking algorithm be updated to include a random wait time to prevent deadlocks while maintaining the privilege of the priority thread to prevent starvation.
Patch checked into 1.1.0 stream.
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink