我在ghc-users邮件列表上的asked this question并获得了一些有用的回复,但仍然不明白此代码中发生了什么。
基本上我试图理解如何捕获异常BlockedIndefinitelyOnMVar以恢复可能尚未返回的锁定,以及一般地理解此异常。
以下是一些单线程代码:
-- This raises the exception only once and the lock is successfully restored:
main1 = do
lock <- newMVar ()
lockPrint "good1" lock
takeMVar lock
putStrLn "main: took lock but didn't return it!"
-- exception is raised and lock is restored here:
lockPrint "good2" lock
-- no exception raised:
lockPrint "good3" lock
readMVar lock
putStrLn "great success"
lockPrint :: String -> MVar () -> IO ()
lockPrint name v = takePrint `finally` put
where put = putMVar v () >> putStrLn (name++": replaced lock")
takePrint = do
e <- try $ takeMVar v :: IO (Either BlockedIndefinitelyOnMVar ())
let printExc = putStrLn . ((name++": ")++) . show
printSuccess = const $ putStrLn (name++": success")
either printExc printSuccess e
以下是展示我不理解的行为的主要版本。特别是我不太确定为什么在main中引发异常,尽管我发现线程并没有像我想象的那样被安排。
main0 = do
lock <- newMVar ()
forkIO $ lockPrint "good1" lock
threadDelay 100000
takeMVar lock
putStrLn "main: took lock but didn't return it!"
-- raises blocked indefinitely exception
forkIO $ lockPrint "good2" lock
-- this should raise no exception if we were successful above:
putStrLn "main: long pause..."
threadDelay 2000000
readMVar lock
putStrLn "great success"
对不起,我很难想出一个更简单的例子。以上内容编译为:ghc --make -threaded -fforce-recomp experiments.hs
答案 0 :(得分:3)
首先尝试处理BlockedIndefinitelyOnMVar
听起来不是一个好主意。使用withMVar
更容易确保始终返回MVar
的内容。有了这个,你不应该首先得到这个异常,除非你有一个死锁(应该被认为是一个错误,应该在代码中修复)。