[
https://issues.apache.org/jira/browse/JCR-2525?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Stephan Huttenhuis updated JCR-2525:
------------------------------------
Status: Patch Available (was: Open)
Concerning your patches. The JCR_Deadlock_changes.diff introduces a
cacheMonitor lock for all methods related to the childNodeEntries object. Then
JCR_Deadlock_additionalChanges.txt uses the NodeState monitor lock for get
methods. This creates 2 different locks for the invariant on childNodeEntries
and this is incorrect. I took the liberty to rewrite the test class to a junit
test (see ItemStateHierarchyManagerDeadlockTest.java).
I have a different proposed solution. A concurrency design rule is to never
give control to a client within a synchronized block. This means that you must
not call methods of which the class has no knowledge of what the method does
and has no control over it (alien methods). In this case calling the listener
is such a situation in NodeState. A solution is to remove the listener
notification calls from the synchronized block and to limit the synchronized
block to the operations on the childNodeEntries object.
Outside the lock a ChildNodeEntry is passed to the listener, but ChildNodeEntry
is immutable and therefore thread-safe. Also the NodeState is passed to the
listener. If the listener calls a method on the NodeState the monitor lock is
aquired again if needed. See JCR-2525-listener-outside-lock.patch (based on the
1.6 branch).
> NodeState and NodeStateListener deadlock
> ----------------------------------------
>
> Key: JCR-2525
> URL: https://issues.apache.org/jira/browse/JCR-2525
> Project: Jackrabbit Content Repository
> Issue Type: Bug
> Components: jackrabbit-core
> Affects Versions: 1.6.1, 1.6.0
> Reporter: Frederic Guilbeault
> Priority: Critical
> Attachments: ItemStateHierarchyManagerDeadlockTest.java,
> JCR-2525-listener-outside-lock.patch, JCR_Deadlock_additionalChanges.txt,
> JCR_Deadlock_changes.diff, JCRDeadlockTest.zip, threads_stuck.txt
>
>
> Java stack information for the threads listed above:
> ===================================================
> "jmssecondaryApplnJobExecutor-8":
> at
> org.apache.jackrabbit.core.state.NodeState.getChildNodeEntry(NodeState.java:300)
> - waiting to lock <0x9e6c6d08> (a
> org.apache.jackrabbit.core.state.NodeState)
> at
> org.apache.jackrabbit.core.CachingHierarchyManager.nodeModified(CachingHierarchyManager.java:316)
> - locked <0xa09882a8> (a java.lang.Object)
> at
> org.apache.jackrabbit.core.CachingHierarchyManager.stateModified(CachingHierarchyManager.java:293)
> at
> org.apache.jackrabbit.core.state.StateChangeDispatcher.notifyStateModified(StateChangeDispatcher.java:111)
> at
> org.apache.jackrabbit.core.state.SessionItemStateManager.stateModified(SessionItemStateManager.java:889)
> at
> org.apache.jackrabbit.core.state.StateChangeDispatcher.notifyStateModified(StateChangeDispatcher.java:111)
> at
> org.apache.jackrabbit.core.state.LocalItemStateManager.stateModified(LocalItemStateManager.java:452)
> at
> org.apache.jackrabbit.core.state.XAItemStateManager.stateModified(XAItemStateManager.java:602)
> at
> org.apache.jackrabbit.core.state.StateChangeDispatcher.notifyStateModified(StateChangeDispatcher.java:111)
> at
> org.apache.jackrabbit.core.state.SharedItemStateManager.stateModified(SharedItemStateManager.java:400)
> at
> org.apache.jackrabbit.core.state.ItemState.notifyStateUpdated(ItemState.java:244)
> at
> org.apache.jackrabbit.core.state.ChangeLog.persisted(ChangeLog.java:297)
> at
> org.apache.jackrabbit.core.state.SharedItemStateManager$Update.end(SharedItemStateManager.java:749)
> at
> org.apache.jackrabbit.core.state.SharedItemStateManager.update(SharedItemStateManager.java:1115)
> at
> org.apache.jackrabbit.core.state.LocalItemStateManager.update(LocalItemStateManager.java:351)
> at
> org.apache.jackrabbit.core.state.XAItemStateManager.update(XAItemStateManager.java:354)
> at
> org.apache.jackrabbit.core.state.LocalItemStateManager.update(LocalItemStateManager.java:326)
> at
> org.apache.jackrabbit.core.state.SessionItemStateManager.update(SessionItemStateManager.java:325)
> at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:1111)
> - locked <0x9b1b0be0> (a org.apache.jackrabbit.core.XASessionImpl)
> at org.apache.jackrabbit.core.SessionImpl.save(SessionImpl.java:915)
> at
> org.apache.jackrabbit.jca.JCASessionHandle.save(JCASessionHandle.java:180)
> ...
> at sun.reflect.GeneratedMethodAccessor1067.invoke(Unknown Source)
> at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
> at java.lang.reflect.Method.invoke(Method.java:597)
> at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:36)
> at sun.reflect.GeneratedMethodAccessor110.invoke(Unknown Source)
> at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
> at java.lang.reflect.Method.invoke(Method.java:597)
> at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:243)
> at
> javax.management.modelmbean.RequiredModelMBean.invokeMethod(RequiredModelMBean.java:1074)
> at
> javax.management.modelmbean.RequiredModelMBean.invoke(RequiredModelMBean.java:955)
> at
> org.springframework.jmx.export.SpringModelMBean.invoke(SpringModelMBean.java:88)
> at
> org.jboss.mx.server.RawDynamicInvoker.invoke(RawDynamicInvoker.java:164)
> at
> org.jboss.mx.modelmbean.RequiredModelMBeanInvoker.invoke(RequiredModelMBeanInvoker.java:127)
> at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:659)
> at
> org.jboss.system.server.jmx.LazyMBeanServer.invoke(LazyMBeanServer.java:291)
> at
> javax.management.MBeanServerInvocationHandler.invoke(MBeanServerInvocationHandler.java:288)
> at $Proxy692.doDiscoveryNow(Unknown Source)
> ...
> at
> org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:531)
> at
> org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:466)
> at
> org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:435)
> at
> org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:322)
> at
> org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:260)
> at
> org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:944)
> at
> org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:868)
> at java.lang.Thread.run(Thread.java:619)
> "jmssecondaryApplnJobExecutor-7":
> at
> org.apache.jackrabbit.core.CachingHierarchyManager.nodeAdded(CachingHierarchyManager.java:362)
> - waiting to lock <0xa09882a8> (a java.lang.Object)
> at
> org.apache.jackrabbit.core.state.StateChangeDispatcher.notifyNodeAdded(StateChangeDispatcher.java:159)
> at
> org.apache.jackrabbit.core.state.SessionItemStateManager.nodeAdded(SessionItemStateManager.java:947)
> at
> org.apache.jackrabbit.core.state.NodeState.notifyNodeAdded(NodeState.java:882)
> at
> org.apache.jackrabbit.core.state.NodeState.addChildNodeEntry(NodeState.java:351)
> - locked <0x9e6c6d08> (a org.apache.jackrabbit.core.state.NodeState)
> at
> org.apache.jackrabbit.core.NodeImpl.createChildNode(NodeImpl.java:541)
> - locked <0xa00619a8> (a org.apache.jackrabbit.core.NodeImpl)
> at
> org.apache.jackrabbit.core.NodeImpl.internalAddChildNode(NodeImpl.java:802)
> at
> org.apache.jackrabbit.core.NodeImpl.internalAddNode(NodeImpl.java:735)
> at
> org.apache.jackrabbit.core.NodeImpl.addNodeWithUuid(NodeImpl.java:2200)
> - locked <0xa00619f8> (a org.apache.jackrabbit.core.NodeImpl)
> at org.apache.jackrabbit.core.NodeImpl.addNode(NodeImpl.java:2133)
> - locked <0xa00619f8> (a org.apache.jackrabbit.core.NodeImpl)
> ...
> at sun.reflect.GeneratedMethodAccessor1067.invoke(Unknown Source)
> at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
> at java.lang.reflect.Method.invoke(Method.java:597)
> at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:36)
> at sun.reflect.GeneratedMethodAccessor110.invoke(Unknown Source)
> at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
> at java.lang.reflect.Method.invoke(Method.java:597)
> at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:243)
> at
> javax.management.modelmbean.RequiredModelMBean.invokeMethod(RequiredModelMBean.java:1074)
> at
> javax.management.modelmbean.RequiredModelMBean.invoke(RequiredModelMBean.java:955)
> at
> org.springframework.jmx.export.SpringModelMBean.invoke(SpringModelMBean.java:88)
> at
> org.jboss.mx.server.RawDynamicInvoker.invoke(RawDynamicInvoker.java:164)
> at
> org.jboss.mx.modelmbean.RequiredModelMBeanInvoker.invoke(RequiredModelMBeanInvoker.java:127)
> at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:659)
> at
> org.jboss.system.server.jmx.LazyMBeanServer.invoke(LazyMBeanServer.java:291)
> at
> javax.management.MBeanServerInvocationHandler.invoke(MBeanServerInvocationHandler.java:288)
> at $Proxy692.doDiscoveryNow(Unknown Source)
> ...
> at
> org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:531)
> at
> org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:466)
> at
> org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:435)
> at
> org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:322)
> at
> org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:260)
> at
> org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:944)
> at
> org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:868)
> at java.lang.Thread.run(Thread.java:619)
> Found 1 deadlock.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.