2.5 Transaction block semantics
2.5.3 Solutions specific to language constructs
2.5.3.2 Exceptions
In considering the interaction of exceptions with transaction blocks, only propagation of an exception out of a transaction block (defined as escaping a transaction block by Adl- Tabatabai et al. [11]) raises semantic issues. Such issues have been brought to the attention of the TM community by Harris [88] and a more thorough discussion of these issues is presented by Crowl et al. [37] and Adl-Tabatabai et al. [11].
There are mainly two alternative behaviors among which a transaction block should choose upon escaping a transaction; commit or abort (Adl-Tabatabai et al. [11] express these behaviors as commit-on-escape and abort-on-escape respectively). Both behaviors raise different semantic issues and, hence, proposed solutions differ according to the chosen behavior:
Commit-on-escape: With these semantics a transaction block commits the modifi- cations it has performed up to the point where the exception is raised and propagates the exception after commit. These semantics allows an exception handler to resolve the exceptional situation by analyzing the state of the system at the time of exception raise and, hence, is compatible with the exception handling mechanism. Ringenburg and Grossman [156] advocate these semantics in their work since they consider the raising of an exception to be a non-local control transfer (which should not change the program state) and the transaction block merely a synchronization construct (so it needs to ensure its guarantees only on error-free situations). Yang et al. [140] adopt these semantics since their implementation of transaction block is based on lock-based semantics and only commit-on-escape semantics correspond to the exception propa- gation semantics of a critical section protected by locks. They also indicate that the use of abort-on-escape semantics for a transaction block enclosing irrevocable code is practically infeasible. It should also be noted that commit-on-escape semantics of a transaction block do not prevent the programmer to mimic the abort-on-escape behavior by explicitly aborting the transaction block upon catching exceptions (which are to be caught inside the transaction block) [37,11].
While commit-on-escape has the assets explained above, it also introduces semantic issues. It allows cases where partial modifications of a transaction block can be visi- ble by other concurrent threads, breaking the atomicity guarantee of the transaction block. This is especially problematic for situations where the program continues to execute after the exception, propagated according to commit-on-escape behavior, has been handled. Such situations imply that a programmer cannot always assume that a transaction block has executed atomically (the block may not have been executed
atomically due to a commit-on-escape behavior) and should take necessary measures to check whether its execution was atomic. In addition, committing a transaction upon an exception, makes an inconsistent system state due to the exceptional sit- uation visible to concurrent threads, threatening the safety of the code (thus also breaking the exception safety suggested by the C++ language [178]).
Abort-on-escape: These semantics suggests that a transaction block rolls all its modifications back before propagating the exception out of the block. As opposed to the commit-on-escape semantics, the abort-on-escape semantics satisfy the require- ments of atomicity guarantee of a transaction block while becoming incompatible with the exception handling mechanism. The incompatibility stems from the fact that the rollback behavior prevents the transfer of information out of transaction block, whereas an exception object is meant to carry information about the excep- tional situation so that the handler can perform necessary actions to correct the situation. This problem can be circumvented by keeping an exception object out of the control of TM during transactification. However, a subtle problem still persists if the exception object has fields referencing to variables allocated during the execution of transaction block: these fields become invalid after the rollback and, hence, cannot be used for handling the exception. Except the exception object referencing allocated variables, transactification techniques are enough to provide the necessary support. Supporting a complete solution require integration techniques to be applied.
Fetzer and Felber [59] suggest that the use of abort-on-escape semantics helps writ- ing more robust exception handling code since, thanks to the rollback behavior, it automatically removes the inconsistencies created by the exceptional situations from the system. Based on the same reasoning, two other studies suggest to augment a try block with transactional semantics (i.e., a try block becomes also a transaction block [30] or an additional try block which has transactional semantics is added to the language [165]). With the abort-on-escape semantics proposed by all these studies, the other semantics, commit-on-escape, can be explicitly coded by the pro- grammer by catching the exception in the transaction block and exiting it without aborting [91,37].
All the above work advocates abort-on-escape but ignores the problem with exception objects enclosing references to variables allocated in the transaction block. Harris et al. [91] propose a partial abort-on-escape semantics such that only write effects of a transaction block are rolled back while allocation effects are retained, avoiding invalid references. However, this solution is quite confusing since part of the exception
object could be rolled back while the rest is not. Another proposition for the problem is making deep copies of the exception objects but this is generally accepted to be infeasible since it is difficult to know the levels of indirections that should be considered to fulfill a deep copy [88,37]. A final proposition is to restrict the types of exceptions (or the types of information) propagating out of a transaction block such that exception objects cannot include references to other variables [37]. This final solution requires the use of the extension technique in order to forbid exceptions not following the restriction.
Since both commit-on-escape and abort-on-escape are useful in different situations, some researchers provided solutions where both semantics can be supported. Adl-Tabatabai et al. [11] use the extension technique and propose a different syntax to the programmer to express both semantics. Harris [88] suggests to distinguish between exceptions that cause abort from the ones that cause commit. He proposes a new base exception type for which abort-on-escape semantics will be applied (obviously descendants of this types will behave the same) while other exceptions will be propagated according to commit-on-escape (this approach requires the integration technique to be applied). Both studies minimize the semantic ambiguity for exception propagation by requiring the programmer to explicitly indicate that s/he desires to use abort-on-escape semantics. This way the programmer knows exactly which semantics s/he should expect for each exceptional situation.