Description of problem: The dispatcher code makes use of DatabaseTransaction class for committing / aborting transactions. This wraps calls to begin/commit/abort in TrnsactionContext so with checks to the inTxn() method. The inTxn() method is modelled with the m_inTxn member variable. There is a problem in the way this variable is updated from the abort/commit events. This code is from the 'commitTxn' method: boolean success = false; try { fireBeforeCommitEvent(); m_ssn.flush(); m_ossn.invalidateDataObjects(true, false); m_ssn.commit(); success = true; m_inTxn = false; fireCommitEvent(); } finally { m_inTxn = false; clearAttributes(); if (!success) { m_ossn.invalidateDataObjects(false, true); } } The import thing to notice is the 'm_inTxn = false' line in the 'finally' block. Consider what happens when fireBeforeCommit throws an exception. The 'm_ssn.commit()' method will never be called, and yet 'm_inTxn' will be toggled to false. The dispatcher later catches the Exception and calls 'DatabaseTransaction#rollback' - but because 'TransactionContext#inTxn()' is now returning false, the DatabaseTransaction object will never call rollback on the underlying TransactionContext object. We now have an open database transaction lieing around holding open locks on a great many tables. This is causes Camden's Production servers to lock up completely about 1-2 times a week. Version-Release number of selected component (if applicable): How reproducible: Steps to Reproduce: 1. Do something that causes beforeCOmmit event to throw an exception 2. Examine locks held in thedatabase & SQL being operated by each connection 3. Actual results: Many sessions are waiting on locks held by an idle connection with an open DB transaction Expected results: Additional info:
committed a tentavie fix at 41194
Looking at the code for 5.2, this needs to be backported too, and likely for 6.0 as well.
Added test at 41464