开发者

Understanding BlockedIndefinitelyOnMVar in Concurrent code

I asked this question on the ghc-users mailing list and got some helpful responses, but still don't understand what is happening in this code.

Essentially I am trying to understand how I can catch the exception BlockedIndefinitelyOnMVar to restore a lock that may have not been returned, and to understand this exception in general.

Here is some single-threaded code that does just that:

-- 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
    --开发者_JS百科 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

And here is the version of main that exhibits the behavior I don't understand. In particular I'm not quite sure why the exception is being raised in main, although I see that the threads aren't really being scheduled as I imagine.

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"

I'm sorry I'm having trouble coming up with a simpler example. The above was compiled with: ghc --make -threaded -fforce-recomp experiments.hs


EDIT: Edward Z. Yang wrote a really lucid blog post on this today here. The upshot being that this exception can't really be relied on for doing anything fancy.


Trying to handle BlockedIndefinitelyOnMVar doesn't sound like a good idea in the first place. It's easier to use withMVar to ensure that the contents of the MVar is always returned. With that, you shouldn't get this exception in the first place, unless you have a deadlock (which should be considered a bug and should be fixed in the code).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜