[ 
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.

Reply via email to