[Haskell-cafe] question about STM and IO

Ryan Ingram ryani.spam at gmail.com
Wed Feb 20 21:02:52 EST 2008

On 2/20/08, Bulat Ziganshin <bulat.ziganshin at gmail.com> wrote:
> STM operations can be repeated if first transaction was unsuccessful.
> so, you may se here only operations that may be safely repeated - say,
> reading/writing memory areas, or reading/writing files, or even
> sending network message as long as its duplication is ok

Actually, you have to be even more careful than that; you may only
include not just operations that may be safely repeated, but
operations that may be erroneously executed.  Consider the following

badNews:: TVar Int -> TVar Int -> IO ()
badNews xRef yRef = atomically $ do
    x <- xRef
    y <- yRef
    if (x < y) then unsafeIOToSTM launchMissiles else return ()

(where launchMissiles has serious side effects, but can be called
repeatedly without problem; the missiles will already have been
launched in the second call).

Even if (x < y) is never "atomically" true, launchMissiles could get
executed during the evaluation of this STM action if it was run
concurrently with another action that wrote new values to x and y in
some order, such as the following snippet

safe :: TVar Int -> TVar Int -> IO ()
safe xRef yRef = do
    atomically $ do
         writeTVar xRef 15
         writeTVar yRef 13

main :: IO ()
main = do
    xRef <- newTVar 10
    yRef <- newTVar 8
    forkIO safe
    forkIO badNews

If "badNews" runs to the point of reading from xRef, then "safe" runs
in its entirety and commits successfully, then badNews resumes,
launchMissiles will get called and then badNews will fail to commit
and be restarted.  The second runthrough of badNews will read the
values, determine that x >= y, and just return (), but it's too late,
the missiles have already been launched.

  -- ryan

More information about the Haskell-Cafe mailing list