Commits

Anonymous committed 0069910

Issue number: QUARTZ-502
When double check locking for cluster checkin, put the checkin before the lock in its own transaction to avoid deadlock conditions (because the checkin can update the scheduler state table)

git-svn-id: http://svn.opensymphony.com/svn/quartz/trunk@63769f7d36a-ea1c-0410-88ea-9fd03e4c9665

Comments (0)

Files changed (1)

src/java/org/quartz/impl/jdbcjobstore/JobStoreSupport.java

         Connection conn = getNonManagedTXConnection();
         try {
             // Other than the first time, always checkin first to make sure there is 
-            // work to be done before we aquire / the lock (since that is expensive, 
-            // and is almost never necessary)
-            List failedRecords = (firstCheckIn) ? null : clusterCheckIn(conn);
+            // work to be done before we aquire the lock (since that is expensive, 
+            // and is almost never necessary).  This must be done in a separate
+            // transaction to prevent a deadlock under recovery conditions.
+            List failedRecords = null;
+            if (firstCheckIn == false) {
+                boolean succeeded = false;
+                try {
+                    failedRecords = clusterCheckIn(conn);
+                    commitConnection(conn);
+                    succeeded = true;
+                } catch (JobPersistenceException e) {
+                    rollbackConnection(conn);
+                    throw e;
+                } finally {
+                    // Only cleanup the connection if we failed and are bailing
+                    // as we will otherwise continue to use it.
+                    if (succeeded == false) {
+                        cleanupConnection(conn);
+                    }
+                }
+            }
             
             if (firstCheckIn || (failedRecords.size() > 0)) {
                 getLockHandler().obtainLock(conn, LOCK_STATE_ACCESS);