Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
MVar deadlock exceptions cause waitCatch to throw an exception #14
import Control.Concurrent import Control.Concurrent.Async import Control.Concurrent.MVar import Control.Exception main :: IO () main = do e <- try $ newEmptyMVar >>= takeMVar print (e :: Either SomeException Int) _ <- forkIO $ do e <- try $ newEmptyMVar >>= takeMVar print ("thread", e :: Either SomeException Int) threadDelay 1000000 putStrLn "calling async" x <- async $ newEmptyMVar >>= takeMVar putStrLn "calling waitCatch" y <- waitCatch x putStrLn "completed waitCatch" print (y :: Either SomeException Int) putStrLn "Exiting..."
There are three logical blocks in this program, each doing essentially the same thing: creating an MVar deadlock exception and trying to catch it. The first approach does it in the main program thread, and the second in a child thread. Both of them work as expected: the exception is caught and printed, and the program continues executing.
However, the third block behaves differently. The MVar exception seems to not be got by the call to
Here's an example output from my system:
I'm on Ubuntu 12.04 64-bit, using GHC 7.8.3, stm-2.4.3 and async-220.127.116.11.
I reduced this to a bug reproducible with just
Feel free to close this issue if you feel it makes more sense to just follow this in GHC trac.
See the comment on https://ghc.haskell.org/trac/ghc/ticket/9401, this isn't really a bug, just a consequence of the way that deadlock detection works.
If you want a particular thread to be immune to deadlock detection, you can use this trick:
Pinging @simonmar. Thank you for your response in the tickets. However, the StablePtr technique simply caused this test suite to hang indefinitely. Instead, I'm trying to catch the BlockedIndefinitelyOnSTM exception sent by the RTS, which seems to work reliably. Pinging @sol. This change needs to be included in hspec as well. Without a patch, for example, the enclosed-exceptions test suite still fails, since hspec ends up letting the test die due to the BlockedIndefinitelyOnSTM exception being sent to it as well. I can send a pull request after this is reviewed/accepted into enclosed-exceptions.
Making a StablePtr will prevent the main thread from receiving deadlock exceptions, so if you need that exception to recover from a main thread deadlock then it will just hang instead. The StablePtr trick works for me on the example in https://ghc.haskell.org/trac/ghc/ticket/9401.
This uses the same technique I described in my enclosed-exceptions pull request. I think it would be better to fix this in async itself, so that other packages trying to use async for reliable exception handling get the semantics they're looking for.