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

Reply via email to