Fix risk of dead-lock in documentation of Control.Concurrent
Bas van Dijk
v.dijk.bas at gmail.com
Mon May 28 00:35:34 CEST 2012
The current documentation of Control.Concurrent proposes a function
to wait for a child thread to complete:
myForkIO :: IO () -> IO (MVar ())
myForkIO io = do
mvar <- newEmptyMVar
forkIO (io `finally` putMVar mvar ())
return mvar
This function has the risk of causing a dead-lock. If an asynchronous
exception if thrown before the putMVar exception handler is installed
the mvar will remain empty. This causes a dead-lock when the mvar is
taken.
The patch attached to the ticket [6126] fixes this problem by
correctly masking asynchronous exceptions before forking. Also,
instead of returning the mvar it returns a computation that waits for
the child thread to complete. This is safer than returning the mvar
itself since a user can't accidentally put the mvar (which will
dead-lock) or take the mvar (which when executed twice will
dead-lock).
The attached patch additionally rewrites the function to wait for a
group of threads to complete. Instead of keeping a list of MVars, I
use a counter (stored in a TVar) that counts the number of running
threads. The counter is incremented when a thread if forked and
decremented when it completes. Waiting for the group of threads to
complete is accomplished by checking if the counter has reached 0 and
if not retry the transaction.
Regards,
Bas
[6126] http://hackage.haskell.org/trac/ghc/ticket/6126
More information about the Libraries
mailing list