Commit 5ea49271 authored by ian@well-typed.com's avatar ian@well-typed.com
Browse files

MERGED: Fix a bug in the handling of nested orElse

    commit f184d9ca
    Author: Simon Marlow <marlowsd@gmail.com>
    Date:   Mon Dec 10 12:00:54 2012 +0000

    Fix a bug in the handling of nested orElse

    Exposed by the following snippet, courtesy of Bas van Dijk and Patrick
    Palka on libraries@haskell.org:

    import Control.Concurrent.STM
    main = do
      x <- atomically $ do
             t <- newTVar 1
             writeTVar t 2
             ((readTVar t >> retry) `orElse` return ()) `orElse` return ()
             readTVar t
      print x
parent 1183080b
......@@ -1447,10 +1447,28 @@ StgBool stmCommitNestedTransaction(Capability *cap, StgTRecHeader *trec) {
StgTVar *s;
s = e -> tvar;
if (entry_is_update(e)) {
// Careful! We might have a read entry here that we don't want
// to spam over the update entry in the enclosing TRec. e.g. in
//
// t <- newTVar 1
// writeTVar t 2
// ((readTVar t >> retry) `orElse` return ()) `orElse` return ()
//
// - the innermost txn first aborts, giving us a read-only entry
// with e->expected_value == e->new_value == 1
// - the inner orElse commits into the outer orElse, which
// lands us here. If we unconditionally did
// merge_update_into(), then we would overwrite the outer
// TRec's update, so we must check whether the entry is an
// update or not, and if not, just do merge_read_into.
//
if (entry_is_update(e)) {
unlock_tvar(trec, s, e -> expected_value, FALSE);
}
merge_update_into(cap, et, s, e -> expected_value, e -> new_value);
merge_update_into(cap, et, s, e -> expected_value, e -> new_value);
} else {
merge_read_into(cap, et, s, e -> expected_value);
}
ACQ_ASSERT(s -> current_value != (StgClosure *)trec);
});
} else {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment