Return-Path: X-Original-To: apmail-cayenne-commits-archive@www.apache.org Delivered-To: apmail-cayenne-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id B1D5F947B for ; Mon, 23 Jan 2012 21:18:05 +0000 (UTC) Received: (qmail 54557 invoked by uid 500); 23 Jan 2012 21:18:05 -0000 Delivered-To: apmail-cayenne-commits-archive@cayenne.apache.org Received: (qmail 54516 invoked by uid 500); 23 Jan 2012 21:18:05 -0000 Mailing-List: contact commits-help@cayenne.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cayenne.apache.org Delivered-To: mailing list commits@cayenne.apache.org Received: (qmail 54497 invoked by uid 99); 23 Jan 2012 21:18:05 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 23 Jan 2012 21:18:05 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED,T_RP_MATCHES_RCVD X-Spam-Check-By: apache.org Received: from [140.211.11.116] (HELO hel.zones.apache.org) (140.211.11.116) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 23 Jan 2012 21:18:03 +0000 Received: from hel.zones.apache.org (hel.zones.apache.org [140.211.11.116]) by hel.zones.apache.org (Postfix) with ESMTP id 4F2B015E93C for ; Mon, 23 Jan 2012 21:17:43 +0000 (UTC) Date: Mon, 23 Jan 2012 21:17:43 +0000 (UTC) From: "Andrus Adamchik (Updated) (JIRA)" To: commits@cayenne.apache.org Message-ID: <1825489812.68325.1327353463326.JavaMail.tomcat@hel.zones.apache.org> Subject: [jira] [Updated] (CAY-957) Deadlock in nested contexts MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-JIRA-FingerPrint: 30527f35849b9dde25b450d4833f0394 [ 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 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