Я задал этот вопрос пользователям ghc список рассылки и получил несколько полезных ответов, но до сих пор не понимаю, что происходит в этом коде.
По сути, я пытаюсь понять, как я могу поймать исключение 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
РЕДАКТИРОВАТЬ: Эдвард З. Ян написал действительно ясный блог пост об этом сегодня здесь. В результате на это исключение нельзя полагаться для выполнения чего-либо необычного.