User: patriot1burke Date: 02/01/12 12:21:07 Modified: src/main/org/jboss/ejb/plugins/lock QueuedPessimisticEJBLock.java BeanLockSupport.java Log: Added deadlock detection. If application deadlock is detected and RuntimeException is thrown so that the thread does not hang until TX timeout. It will be extremely helpful in debugging. Revision Changes Path 1.8 +81 -54 jboss/src/main/org/jboss/ejb/plugins/lock/QueuedPessimisticEJBLock.java Index: QueuedPessimisticEJBLock.java =================================================================== RCS file: /cvsroot/jboss/jboss/src/main/org/jboss/ejb/plugins/lock/QueuedPessimisticEJBLock.java,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- QueuedPessimisticEJBLock.java 2001/12/19 06:04:48 1.7 +++ QueuedPessimisticEJBLock.java 2002/01/12 20:21:07 1.8 @@ -36,7 +36,7 @@ * @author <a href="[EMAIL PROTECTED]">Marc Fleury</a> * @author <a href="[EMAIL PROTECTED]">Bill Burke</a> * - * @version $Revision: 1.7 $ + * @version $Revision: 1.8 $ * * <p><b>Revisions:</b><br> * <p><b>2001/08/03: billb</b> @@ -238,59 +238,85 @@ protected boolean waitForTx(Transaction miTx, boolean trace) throws Exception { boolean wasScheduled = false; - - // Do we have a running transaction with the context? - // We loop here until either until success or until transaction timeout - // If we get out of the loop successfully, we can successfully - // set the transaction on this puppy. - while (this.tx != null && - // And are we trying to enter with another transaction? - !this.tx.equals(miTx)) - { - wasScheduled = true; - // That's no good, only one transaction per context - // Let's put the thread to sleep the transaction demarcation will wake them up - if( trace ) log.trace("Transactional contention on context"+id); - - TxLock txLock = getTxLock(miTx); - - if( trace ) log.trace("Begin wait on Tx="+this.tx); - - // And lock the threads on the lock corresponding to the Tx in MI - synchronized(txLock) - { - releaseSync(); - try - { - txLock.wait(txTimeout); - } catch (InterruptedException ignored) {} - } // end synchronized(txLock) - - this.sync(); - - if( trace ) log.trace("End wait on TxLock="+this.tx); - if (isTxExpired(miTx)) - { - log.error(Thread.currentThread() + "Saw rolled back tx="+miTx+" waiting for txLock" - // +" On method: " + mi.getMethod().getName() - // +" txWaitQueue size: " + txWaitQueue.size() - ); - if (txLock.isQueued) - { - // Remove the TxLock from the queue because this thread is exiting. - // Don't worry about notifying other threads that share the same transaction. - // They will timeout and throw the below RuntimeException - txLocks.remove(txLock); - txWaitQueue.remove(txLock); - } - else if (this.tx != null && tx.equals(miTx)) - { - // We're not qu - nextTransaction(); - } - throw new RuntimeException("Transaction marked for rollback, possibly a timeout"); - } - } // end while(tx!=miTx) + boolean addedWaiting = false; + try + { + // Do we have a running transaction with the context? + // We loop here until either until success or until transaction timeout + // If we get out of the loop successfully, we can successfully + // set the transaction on this puppy. + while (this.tx != null && + // And are we trying to enter with another transaction? + !this.tx.equals(miTx)) + { + // For deadlock detection. + // miTx is waiting for this.tx to finish so put it + // in the waiting table and do deadlock detection. + if (miTx != null && !addedWaiting) + { + synchronized (waiting) + { + waiting.put(miTx, this.tx); + addedWaiting = true; + } + deadlockDetection(miTx); + } + wasScheduled = true; + // That's no good, only one transaction per context + // Let's put the thread to sleep the transaction demarcation will wake them up + if( trace ) log.trace("Transactional contention on context"+id); + + TxLock txLock = getTxLock(miTx); + + if( trace ) log.trace("Begin wait on Tx="+this.tx); + + // And lock the threads on the lock corresponding to the Tx in MI + synchronized(txLock) + { + releaseSync(); + try + { + txLock.wait(txTimeout); + } catch (InterruptedException ignored) {} + } // end synchronized(txLock) + + this.sync(); + + if( trace ) log.trace("End wait on TxLock="+this.tx); + if (isTxExpired(miTx)) + { + log.error(Thread.currentThread() + "Saw rolled back tx="+miTx+" waiting for txLock" + // +" On method: " + mi.getMethod().getName() + // +" txWaitQueue size: " + txWaitQueue.size() + ); + if (txLock.isQueued) + { + // Remove the TxLock from the queue because this thread is exiting. + // Don't worry about notifying other threads that share the same transaction. + // They will timeout and throw the below RuntimeException + txLocks.remove(txLock); + txWaitQueue.remove(txLock); + } + else if (this.tx != null && tx.equals(miTx)) + { + // We're not qu + nextTransaction(); + } + throw new RuntimeException("Transaction marked for rollback, possibly a timeout"); + } + } // end while(tx!=miTx) + } + finally + { + // miTx is now long waiting for a tx to finish so remove it from the waiting table. + if (miTx != null && addedWaiting) + { + synchronized (waiting) + { + waiting.remove(miTx); + } + } + } // If we get here, this means that we have the txlock this.tx = miTx; @@ -444,5 +470,6 @@ System.out.println(Thread.currentThread() + " removing lock!"); */ } + } 1.10 +31 -1 jboss/src/main/org/jboss/ejb/plugins/lock/BeanLockSupport.java Index: BeanLockSupport.java =================================================================== RCS file: /cvsroot/jboss/jboss/src/main/org/jboss/ejb/plugins/lock/BeanLockSupport.java,v retrieving revision 1.9 retrieving revision 1.10 diff -u -r1.9 -r1.10 --- BeanLockSupport.java 2001/12/19 06:04:48 1.9 +++ BeanLockSupport.java 2002/01/12 20:21:07 1.10 @@ -15,6 +15,8 @@ import org.jboss.ejb.BeanLock; import org.jboss.invocation.Invocation; import org.jboss.logging.Logger; +import java.util.HashMap; +import java.util.HashSet; /** @@ -22,7 +24,7 @@ * * @author <a href="[EMAIL PROTECTED]">Bill Burke</a> * @author <a href="[EMAIL PROTECTED]">Marc Fleury</a> - * @version $Revision: 1.9 $ + * @version $Revision: 1.10 $ * * <p><b>Revisions:</b><br> * <p><b>2001/07/29: marcf</b> @@ -164,5 +166,33 @@ } return false; + } + + // This following is for deadlock detection + protected static HashMap waiting = new HashMap(); + + public void deadlockDetection(Transaction miTx) + { + HashSet set = new HashSet(); + set.add(miTx); + + Object checkTx = this.tx; + synchronized(waiting) + { + while (checkTx != null) + { + Object waitingFor = waiting.get(checkTx); + if (waitingFor != null) + { + if (set.contains(waitingFor)) + { + log.error("Application deadlock detected: " + miTx + " has deadlock conditions"); + throw new RuntimeException("application deadlock detected"); + } + set.add(waitingFor); + } + checkTx = waitingFor; + } + } } }
_______________________________________________ Jboss-development mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/jboss-development