I created this small program that creates a long-running thunk that eventually fails with an exception. Then, multiple threads try to evaluate it.
import Control.Monad
import Control.Concurrent
import Control.Concurrent.MVar
main = do
let thunk = let p = product [1..10^4]
in if p `mod` 2 == 0 then error "exception"
else ()
children <- replicateM 2000 (myForkIO (print thunk))
mapM_ takeMVar children
-- | Spawn a thread and return a MVar which can be used to wait for it.
myForkIO :: IO () -> IO (MVar ())
myForkIO io = do
mvar <- newEmptyMVar
forkFinally io (\_ -> putMVar mvar ())
return mvar
Increasing the number of threads has clearly no impact on the computation, which suggests that a failed thunk keeps the exception as the result. Is it true? Is this behavior documented/specified somewhere?
Update: Changing the forkFinally
line to
forkFinally io (\e -> print e >> putMVar mvar ())
confirms that each thread fails with the exception.
ghc-heap-view
, so I am not sure what more do you need. Can you please clarify your question if my answer is not helpful enough? – Juttajutty