Commit 5e91cdec authored by David Feuer's avatar David Feuer Committed by David Feuer

Unmask readMVar in readChan

When `readMVar` was implemented using `takeMVar` and `putMVar`,
we needed to use `modifyMVarMasked` in `readChan` just in case
the `readMVar` was interrupted between taking and putting. Now
that `readMVar` uses an atomic primop, this is impossible, so we can
safely unmask `readMVar`.

Reviewers: hvr, bgamari, simonmar

Reviewed By: simonmar

Subscribers: rwbarton, thomie, carter

Differential Revision:
parent 576078a8
......@@ -106,21 +106,12 @@ writeChan (Chan _ writeVar) val = do
-- thread holds a reference to the channel.
readChan :: Chan a -> IO a
readChan (Chan readVar _) = do
modifyMVarMasked readVar $ \read_end -> do -- Note [modifyMVarMasked]
modifyMVar readVar $ \read_end -> do
(ChItem val new_read_end) <- readMVar read_end
-- Use readMVar here, not takeMVar,
-- else dupChan doesn't work
return (new_read_end, val)
-- Note [modifyMVarMasked]
-- This prevents a theoretical deadlock if an asynchronous exception
-- happens during the readMVar while the MVar is empty. In that case
-- the read_end MVar will be left empty, and subsequent readers will
-- deadlock. Using modifyMVarMasked prevents this. The deadlock can
-- be reproduced, but only by expanding readMVar and inserting an
-- artificial yield between its takeMVar and putMVar operations.
-- |Duplicate a 'Chan': the duplicate channel begins empty, but data written to
-- either channel from then on will be available from both. Hence this creates
-- a kind of broadcast channel, where data written by anyone is seen by
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