[ 
https://issues.apache.org/jira/browse/CAY-957?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Andrus Adamchik updated CAY-957:
--------------------------------

    Attachment: 0001-CAY-957-Deadlock-in-nested-contexts.patch

Here is a unit test against 3.1M3+ that demonstrates the deadlock. After 
CAY-1653 fix cleared one deadlock, it now happens between parent and child 
ObjectStores (a classic situation)  - 

"UpdateThread-1":
        at 
org.apache.cayenne.access.DataContextMergeHandler.graphChanged(DataContextMergeHandler.java:103)
        - waiting to lock <7f4316d78> (a org.apache.cayenne.access.ObjectStore)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.cayenne.util.Invocation.fire(Invocation.java:202)
        at 
org.apache.cayenne.event.DefaultEventManager$Dispatch.fire(DefaultEventManager.java:400)
        at 
org.apache.cayenne.event.DispatchQueue.dispatchEvent(DispatchQueue.java:162)
        at 
org.apache.cayenne.event.DispatchQueue.dispatchEvent(DispatchQueue.java:65)
        at 
org.apache.cayenne.event.DefaultEventManager.dispatchEvent(DefaultEventManager.java:339)
        at 
org.apache.cayenne.event.DefaultEventManager.postEvent(DefaultEventManager.java:310)
        at 
org.apache.cayenne.BaseContext.fireDataChannelChanged(BaseContext.java:565)
        at 
org.apache.cayenne.access.DataContext.fireDataChannelChanged(DataContext.java:1194)
        at 
org.apache.cayenne.access.DataContext.onContextFlush(DataContext.java:770)
        at org.apache.cayenne.BaseContext.onSync(BaseContext.java:516)
        at 
org.apache.cayenne.access.DataContext.flushToParent(DataContext.java:816)
        - locked <7f435cfe0> (a org.apache.cayenne.access.ObjectStore)
        at 
org.apache.cayenne.access.DataContext.commitChanges(DataContext.java:755)
        at 
org.apache.cayenne.access.NestedDataContext_DeadlockTest$UpdateThread.run(NestedDataContext_DeadlockTest.java:121)
"UpdateThread-0":
        at 
org.apache.cayenne.access.DataContextMergeHandler.graphChanged(DataContextMergeHandler.java:103)
        - waiting to lock <7f435cfe0> (a org.apache.cayenne.access.ObjectStore)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.cayenne.util.Invocation.fire(Invocation.java:202)
        at 
org.apache.cayenne.event.DefaultEventManager$Dispatch.fire(DefaultEventManager.java:400)
        at 
org.apache.cayenne.event.DispatchQueue.dispatchEvent(DispatchQueue.java:162)
        at 
org.apache.cayenne.event.DispatchQueue.dispatchEvent(DispatchQueue.java:65)
        at 
org.apache.cayenne.event.DefaultEventManager.dispatchEvent(DefaultEventManager.java:339)
        at 
org.apache.cayenne.event.DefaultEventManager.postEvent(DefaultEventManager.java:310)
        at 
org.apache.cayenne.BaseContext.fireDataChannelChanged(BaseContext.java:565)
        at 
org.apache.cayenne.access.DataContext.fireDataChannelChanged(DataContext.java:1194)
        at 
org.apache.cayenne.access.DataContext.onContextFlush(DataContext.java:770)
        at org.apache.cayenne.BaseContext.onSync(BaseContext.java:516)
        at 
org.apache.cayenne.access.DataContext.flushToParent(DataContext.java:816)
        - locked <7f4316d78> (a org.apache.cayenne.access.ObjectStore)
        at 
org.apache.cayenne.access.DataContext.commitChanges(DataContext.java:755)
        at 
org.apache.cayenne.access.NestedDataContext_DeadlockTest$UpdateThread.run(NestedDataContext_DeadlockTest.java:121)

Found 1 deadlock.


                
> Deadlock in nested contexts
> ---------------------------
>
>                 Key: CAY-957
>                 URL: https://issues.apache.org/jira/browse/CAY-957
>             Project: Cayenne
>          Issue Type: Bug
>          Components: Core Library
>    Affects Versions: 1.2 branch, 2.0 branch, 3.0
>            Reporter: Andrus Adamchik
>            Assignee: Andrus Adamchik
>             Fix For: Short term future
>
>         Attachments: 0001-CAY-957-Deadlock-in-nested-contexts.patch
>
>
> There is a deadlock condition when two peer nested contexts commit 
> simultaneously. Here is a small test case:
> package org.test;
> import java.util.Date;
> import java.util.List;
> import java.util.Random;
> import org.apache.cayenne.access.DataContext;
> import org.apache.cayenne.query.EJBQLQuery;
> public class Main {
>       public static void main(String[] args) {
>               DataContext parent = DataContext.createDataContext();
>               parent.performGenericQuery(new EJBQLQuery("delete from 
> Artist"));
>               for (int i = 0; i < 300; i++) {
>                       Artist a = parent.newObject(Artist.class);
>                       a.setArtistName("X" + i);
>                       a.setDateOfBirth(new Date());
>               }
>               parent.commitChanges();
>               Random rnd = new Random(System.currentTimeMillis());
>               for (int i = 0; i < 2; i++) {
>                       new UpdateThread(parent.createChildDataContext(), 
> rnd).start();
>               }
>               synchronized (parent) {
>                       try {
>                               parent.wait();
>                       } catch (InterruptedException e) {
>                               // TODO Auto-generated catch block
>                               e.printStackTrace();
>                       }
>               }
>       }
>       static class UpdateThread extends Thread {
>               protected DataContext context;
>               protected Random rnd;
>               UpdateThread(DataContext context, Random rnd) {
>                       super("UpdateThread-" + context.hashCode());
>                       setDaemon(true);
>                       this.context = context;
>                       this.rnd = rnd;
>               }
>               @Override
>               public void run() {
>                       List<Artist> artists = context.performQuery(new 
> EJBQLQuery(
>                                       "select a FROM Artist a"));
>                       for (int i = 0; i < 1000; i++) {
>                               for (int j = 0; j < 5; j++) {
>                                       int index = rnd.nextInt(artists.size());
>                                       Artist a = artists.get(index);
>                                       a.setArtistName("Y" + rnd.nextInt());
>                               }
>                               context.commitChanges();
>                               System.out.println(getId() + ": " + i);
>                       }
>               }
>       }
> }
> It deadlocks almost immediately with only two threads... Here is the stacks 
> from Jconsole:
> Name: UpdateThread-9684455
> State: BLOCKED on org.apache.cayenne.event.DispatchQueue@f899e9 owned by: 
> UpdateThread-10872036
> Total blocked: 7  Total waited: 1
> Stack trace: 
> org.apache.cayenne.event.DispatchQueue.dispatchEvent(DispatchQueue.java:54)
> org.apache.cayenne.event.EventManager.dispatchEvent(EventManager.java:348)
> org.apache.cayenne.event.EventManager.postEvent(EventManager.java:319)
> org.apache.cayenne.access.DataContext.fireDataChannelChanged(DataContext.java:1457)
> org.apache.cayenne.access.DataContext.onContextFlush(DataContext.java:1121)
> org.apache.cayenne.access.DataContext.onSync(DataContext.java:1102)
> org.apache.cayenne.access.DataContext.flushToParent(DataContext.java:1160)
> org.apache.cayenne.access.DataContext.commitChanges(DataContext.java:1073)
> org.test.Main$UpdateThread.run(Main.java:66)
> Name: UpdateThread-10872036
> State: BLOCKED on org.apache.cayenne.access.ObjectStore@1b9b03 owned by: 
> UpdateThread-9684455
> Total blocked: 9  Total waited: 0
> Stack trace: 
> org.apache.cayenne.access.DataContextMergeHandler.graphChanged(DataContextMergeHandler.java:104)
> sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
> java.lang.reflect.Method.invoke(Method.java:585)
> org.apache.cayenne.util.Invocation.fire(Invocation.java:204)
> org.apache.cayenne.event.EventManager$Dispatch.fire(EventManager.java:409)
> org.apache.cayenne.event.DispatchQueue.dispatchEvent(DispatchQueue.java:162)
> org.apache.cayenne.event.DispatchQueue.dispatchEvent(DispatchQueue.java:58)
> org.apache.cayenne.event.EventManager.dispatchEvent(EventManager.java:348)
> org.apache.cayenne.event.EventManager.postEvent(EventManager.java:319)
> org.apache.cayenne.access.DataContext.fireDataChannelChanged(DataContext.java:1457)
> org.apache.cayenne.access.DataContext.onContextFlush(DataContext.java:1121)
> org.apache.cayenne.access.DataContext.onSync(DataContext.java:1102)
> org.apache.cayenne.access.DataContext.flushToParent(DataContext.java:1160)
> org.apache.cayenne.access.DataContext.commitChanges(DataContext.java:1073)
> org.test.Main$UpdateThread.run(Main.java:66)

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: 
https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

Reply via email to