[ http://issues.apache.org/jira/browse/IBATIS-286?page=all ] Clinton Begin closed IBATIS-286: --------------------------------
Resolution: Fixed fixed as described > race-condition bug causing transactions to fail due to SessionScope to be in > an inconsistent state. > --------------------------------------------------------------------------------------------------- > > Key: IBATIS-286 > URL: http://issues.apache.org/jira/browse/IBATIS-286 > Project: iBatis for Java > Type: Bug > Components: SQL Maps > Versions: 2.1.7 > Environment: JDK 1.4.2 > SunOS eqd-dev8.uk.jpmorgan.com 5.8 Generic_117350-28 sun4u sparc > SUNW,Sun-Fire-480R > Reporter: Scott William Sinclair > > Summary: > Discovered a race-condition bug which causes the > com.ibatis.sqlmap.engine.transaction.TransactionManager to throw exceptions > due to the com.ibatis.sqlmap.engine.scope.SessionScope being in an > inconsistent state. > The transaction manager checks the > com.ibatis.sqlmap.engine.transaction.TransactionState > (STATE_STARTED,STATE_COMMITTED,STATE_ENDED,STATE_USER_PROVIDED) of the > SessionScope and throws an exception if it is not in the expected state. > Worked Example: > a SqlMapSessionImpl s1 is created for a thread t1 and a session scope ss1 is > popped from the pool > s1.setUserConnection(con) is called to perform a user-controlled > transaction > the transaction executes normally > s1.setUserConnection(null) is called to free up the connection as > specified in the iBatis docs > The SessionScope ss1 is pushed back into the pool for later use > a SqlMapSessionImpl s2 is created for a thread t2 and session scope ss1 is > popped from the pool again > s2.startTransaction(...) is called to start a conventional iBatis > managed transaction on thread t2 with SessionScope ss1 > s1.startTransaction(...) is called to start a conventional iBatis > managed transaction on thread t1 with SessionScope ss1 > thread t1 throws the exception <INSERT HERE> > this is because SessionScope ss1 has been initialized by > s2.startTransaction() causing the s1.startTransaction() to fail due to the > unexpected state of ss1. > SqlMapSessionImpl s1 is closed and SessionScope ss1 is returned to the > pool for later use. > s2.execute(...) is called to execute statements > s2.commitTransaction(...) is called to commit the iBatis managed > transaction > s2.endTransaction(...) is called to complete the iBatis managed > transaction > this closes SqlMapSessionImpl s2, and SessionScope ss1 is returned to > the pool for later use. > SessionScope ss1 is now in the pool twice, causing ss1 to be available > to multiple threads. > This results in the same race condition reoccurring. > > Fix: > Ensure that SqlMapSessionImpl is closed when > SqlMapSessionImpl.setUserConnection(null) is called. > Class com.ibatis.sqlmap.engine.impl.SqlMapClientImpl: > public void setUserConnection(Connection connection) throws SQLException { > try { > getLocalSqlMapSession().setUserConnection(connection); > } finally { > if (connection == null) { //bug fix:if connection == null, close the > session like we are ending a transaction > getLocalSqlMapSession().close(); > } > } > } > Remove the push(SessionScope) call in > SqlMapExecutorDelegate.setUserProvidedTransaction(SessionScope session, > Connection userConnection) when userConnection is null. This makes sure that > the SessionScope is not pushed twice. > Class com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate: > public void setUserProvidedTransaction(SessionScope session, Connection > userConnection) { > if (session.getTransactionState() == TransactionState.STATE_USER_PROVIDED) { > session.recallTransactionState(); > } > if (userConnection != null) { > Connection conn = userConnection; > session.saveTransactionState(); > session.setTransaction(new UserProvidedTransaction(conn)); > session.setTransactionState(TransactionState.STATE_USER_PROVIDED); > } else { > session.setTransaction(null); > //pushSession(session); bug fix: commented out done as part of closing > the SqlMapSessionImpl > } > } -- This message is automatically generated by JIRA. - If you think it was sent incorrectly contact one of the administrators: http://issues.apache.org/jira/secure/Administrators.jspa - For more information on JIRA, see: http://www.atlassian.com/software/jira