You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by kr...@apache.org on 2011/10/10 08:38:53 UTC

svn commit: r1180790 - /db/derby/code/trunk/java/engine/org/apache/derby/impl/services/daemon/IndexStatisticsDaemonImpl.java

Author: kristwaa
Date: Mon Oct 10 06:38:52 2011
New Revision: 1180790

URL: http://svn.apache.org/viewvc?rev=1180790&view=rev
Log:
DERBY-5447: Deadlock in AutomaticIndexStatisticsTest.testShutdownWhileScanningThenDelete (BasePage.releaseExclusive and Observable.deleteObserver (BaseContainerHandle)) 

Clean the daemon context only after the running worker thread (if any) has
finished to avoid Java deadlock when closing the container handles obtained
with the context.
The deadlock is intermittent, but can easily be reproduced, and involves
synchronization in BasePage and in java.util.Observable.

Patch file: derby-5447-2a-change_istat_shutdown.diff


Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/services/daemon/IndexStatisticsDaemonImpl.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/services/daemon/IndexStatisticsDaemonImpl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/services/daemon/IndexStatisticsDaemonImpl.java?rev=1180790&r1=1180789&r2=1180790&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/services/daemon/IndexStatisticsDaemonImpl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/services/daemon/IndexStatisticsDaemonImpl.java Mon Oct 10 06:38:52 2011
@@ -886,9 +886,14 @@ public class IndexStatisticsDaemonImpl
      */
     public void stop() {
         Thread threadToWaitFor = null;
+        // Controls execution of last cleanup step outside of the synchronized
+        // block. Should only be done once, and this is ensured by the guard on
+        // 'queue' and the value of 'daemonDisabled'.
+        boolean clearContext = false;
 
         synchronized (queue) {
             if (!daemonDisabled) {
+                clearContext = true;
                 StringBuffer sb = new StringBuffer(100);
                 sb.append("stopping daemon, active=").
                         append(runningThread != null).
@@ -913,12 +918,7 @@ public class IndexStatisticsDaemonImpl
                 threadToWaitFor = runningThread;
                 runningThread = null;
                 queue.clear();
-                // DERBY-5336: Trigger cleanup code to remove the context
-                //             from the context service. This pattern was
-                //             copied from BasicDaemon.
-                ctxMgr.cleanupOnError(StandardException.normalClose(), false);
             }
-
         }
 
         // Wait for the currently running thread, if there is one. Must do
@@ -935,6 +935,17 @@ public class IndexStatisticsDaemonImpl
             }
 
         }
+
+        // DERBY-5447: Remove the context only after the running daemon thread
+        //             (if any) has been shut down to avoid Java deadlocks
+        //             when closing the container handles obtained with this
+        //             context.
+        if (clearContext) {
+            // DERBY-5336: Trigger cleanup code to remove the context
+            //             from the context service. This pattern was
+            //             copied from BasicDaemon.
+            ctxMgr.cleanupOnError(StandardException.normalClose(), false);
+        }
     }