Why does com.arjuna.ats.internal.jts.orbspecific.coordinator.ArjunaTransactionImple throw INVALID or Inactive when we know the status is ABORTED?
by Tomasz Adamski
I have hit a race condition where the EJB interceptors and the reaper are both aborting a transaction simultaneously. If the reaper doesn't finish rollback before ejb thread enters it then the ejb thread gets INVALID_TRANSACTION (via ArjunaTransactionImple) (even though the transaction is still on the thread). ArjunaTransactionImple knows that the status is ActionStatus.ABORTED but elects to throw INVALID_TRANSACTION. By changing the code to throw TRANSACTION_ROLLEDBACK instead the EJB interceptor thread can correctly reason about the aborted transaction.
More specifically, here are the two possible outcomes depending on the order in which both threads execute com.arjuna.ats.internal.jts.ControlWrapper code:
Scenario 1:
* reaper executes ControlWrapper#rollback method first
* server executes ControlWrapper#rollback; line _controlImpl.getImplHandle().rollback() throws an NullPointerException as ArjunaTransactionImple has been already detached exception is caught and TransactionRolledbackException is thrown
Scenario 2:
* both threads enter ControlWrapper#rollback at the same time
* server thread obtains ArjunaTransactionImple; transaction is in ABORTED state so InvalidTransaction exception is thrown
Attempt to synchronize the code:
synchronized (_controlImpl) {
_controlImpl.getImplHandle().rollback();
}
on _controlImpl object doesn't work as it introduces possible deadlock to the code. Another possibility would be to check transaction status inside ArjunaTransactionImple#rollback method and throw TransactionRolledbackException when transaction is already aborted. I have tested such fix in my branch and it fixes the initial error - TransactionRolledbackException is thrown consistently.
Is such fix possible to introduce? Are there some problems that it may introduce?
--
Tomasz Adamski
Software Engineer
JBoss by Red Hat
8 years, 3 months