Normal top-level STM transactions (e.g. initiated by an atomically call in
Haskell) by definition should have enclosing_trec == NO_TREC. The
ATOMICALLY_FRAME handler in raiseAsync checks this invariant with an assert.
In the case of nested transactions initiated by orElse we will hit a
CATCH_RETRY_FRAME before hitting an ATOMICALLY_FRAME, avoiding this
However, in the case of nested transactions started by the STM machinery for the
purpose that we are checking invariants we have no such CATCH_RETRY_FRAME.
stg_atomically_frame just pushes an ATOMICALLY_FRAME. Since this frame will
have enclosing_trec != NO_TREC, this trips the assertion.
Consequently, the existence of invariants means we must refine the assertion in
raiseAsync: We now assert that,
- We in a invariant-checking transaction and therefore atomically_frame->next_invariant_to_check != END_INVARIANT_CHECK_QUEUE, or
- We are in a normal, top-level transaction and therefore tso->trec->enclosing_trec == NO_TREC