Admin message

Due to a large amount of spam we do not allow new users to create repositories, they are "external" users. If you are a new user and want to create a repository, for example for forking GHC, open a new issue on ghc/ghc using the "get-verified" issue template

BlockedIndefinitelyOnMVar thrown to the thread which is not blocked indefinitely
BlockedIndefinatelyOnMVar exception is thrown to the main thread in below source code although the thread is not blocked indefinitely. ```hs module Main where import qualified Control.Concurrent.MVar as MV import qualified Control.Concurrent as CC import qualified Control.Exception as E main :: IO () main = do -- call this thread "threadA" mvar1 <- MV.newEmptyMVar :: IO (MV.MVar ()) mvar2 <- MV.newEmptyMVar :: IO (MV.MVar ()) _ <- CC.forkIO $ do -- call this thread "threadB" MV.takeMVar mvar1 `E.catch` errorHandler1 putStrLn "after error catch" CC.threadDelay 1000000 MV.putMVar mvar2 () putStrLn "after putMVar" MV.readMVar mvar2 `E.catch` errorHandler2 putStrLn "after readMVar" CC.threadDelay 5000000 where errorHandler1 :: E.BlockedIndefinitelyOnMVar -> IO () errorHandler1 e = putStrLn $ "errorHandler1 : " ++ show e errorHandler2 :: E.BlockedIndefinitelyOnMVar -> IO () errorHandler2 e = putStrLn $ "errorHandler2 : " ++ show e ``` Save above as "mvar.hs" and run by ghc as below. ``` > runhaskell mvar.hs errorHandler1 : thread blocked indefinitely in an MVar operation errorHandler2 : thread blocked indefinitely in an MVar operation after error catch after readMVar after putMVar ``` BlockedIndefinitelyOnMVar thrown for mvar1 is correct. It will be caught by errorHandler1 and "threadB" can continue to put the value to mvar2. It means that "threadA" can wait for the value of mvar2 and it is not blocked indefinately. However, BlockedIndefinitelyOnMVar is thrown for mvar2 on "threadA" before "threadB" puts value to the mvar2. I think it is incorrect. ---- I tested another case that adding "CC.threadDelay 10000000" before "readMVar" as below. ```hs module Main where import qualified Control.Concurrent.MVar as MV import qualified Control.Concurrent as CC import qualified Control.Exception as E main :: IO () main = do -- call this thread "threadA" mvar1 <- MV.newEmptyMVar :: IO (MV.MVar ()) mvar2 <- MV.newEmptyMVar :: IO (MV.MVar ()) _ <- CC.forkIO $ do -- call this thread "threadB" MV.takeMVar mvar1 `E.catch` errorHandler1 putStrLn "after error catch" CC.threadDelay 1000000 MV.putMVar mvar2 () putStrLn "after putMVar" CC.threadDelay 10000000 -- <-- this line is added MV.readMVar mvar2 `E.catch` errorHandler2 putStrLn "after readMVar" CC.threadDelay 5000000 where errorHandler1 :: E.BlockedIndefinitelyOnMVar -> IO () errorHandler1 e = putStrLn $ "errorHandler1 : " ++ show e errorHandler2 :: E.BlockedIndefinitelyOnMVar -> IO () errorHandler2 e = putStrLn $ "errorHandler2 : " ++ show e ``` And it will run correctly (BlockedIndefinitelyOnMVar is not thrown for mvar2). ``` > runhaskell mvar.hs errorHandler1 : thread blocked indefinitely in an MVar operation after error catch after putMVar after readMVar ``` ---- I found this behavior is same on STM / BlockedIndefinitelyOnSTM. ```hs module Main where import qualified Control.Concurrent.STM as STM import qualified Control.Concurrent as CC import qualified Control.Exception as E main :: IO () main = do tmv1 <- STM.newEmptyTMVarIO :: IO (STM.TMVar ()) tmv2 <- STM.newEmptyTMVarIO :: IO (STM.TMVar ()) _ <- CC.forkIO $ do STM.atomically (STM.takeTMVar tmv1) `E.catch` errorHandler1 putStrLn "after error catch" CC.threadDelay 1000000 STM.atomically $ STM.putTMVar tmv2 () putStrLn "after putTMVar" STM.atomically (STM.readTMVar tmv2) `E.catch` errorHandler2 putStrLn "after readTMVar" CC.threadDelay 5000000 where errorHandler1 :: E.BlockedIndefinitelyOnSTM -> IO () errorHandler1 e = putStrLn $ "errorHandler1 : " ++ show e errorHandler2 :: E.BlockedIndefinitelyOnSTM -> IO () errorHandler2 e = putStrLn $ "errorHandler2 : " ++ show e ``` ``` > runhaskell stm.hs errorHandler1 : thread blocked indefinitely in an STM transaction errorHandler2 : thread blocked indefinitely in an STM transaction after error catch after readTMVar after putTMVar ``` ---- I tested this in below versions/OSs and got same result (exception thrown for mvar2/tmv2). ghc7.8.3 on Windows7 ghc7.8.3 on lubuntu14.04 on VirtualBox on Windows7 ghc7.8.4 on lubuntu14.04 on VirtualBox on Windows7 ghc7.10.1 on lubuntu14.04 on VirtualBox on Windows7 Similar report #8804 found but not the same. (In this case, the reference to the MVar is not weak) <details><summary>Trac metadata</summary> | Trac field | Value | | ---------------------- | -------------- | | Version | 7.8.3 | | Type | Bug | | TypeOfFailure | OtherFailure | | Priority | normal | | Resolution | Unresolved | | Component | Runtime System | | Test case | | | Differential revisions | | | BlockedBy | | | Related | | | Blocking | | | CC | simonmar | | Operating system | | | Architecture | | </details> <!-- {"blocked_by":[],"summary":"BlockedIndefinitelyOnMVar thrown to the thread which is not blocked indefinitely","status":"New","operating_system":"","component":"Runtime System","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"OwnedBy","contents":"simonmar"},"version":"7.8.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":["simonmar"],"type":"Bug","description":"BlockedIndefinatelyOnMVar exception is thrown to the main thread in below source code although the thread is not blocked indefinitely.\r\n\r\n{{{#!hs\r\nmodule Main where\r\n\r\nimport qualified Control.Concurrent.MVar as MV\r\nimport qualified Control.Concurrent as CC\r\nimport qualified Control.Exception as E\r\n\r\nmain :: IO ()\r\nmain = do\r\n -- call this thread \"threadA\"\r\n mvar1 <- MV.newEmptyMVar :: IO (MV.MVar ())\r\n mvar2 <- MV.newEmptyMVar :: IO (MV.MVar ())\r\n _ <- CC.forkIO $ do\r\n -- call this thread \"threadB\"\r\n MV.takeMVar mvar1 `E.catch` errorHandler1\r\n putStrLn \"after error catch\"\r\n CC.threadDelay 1000000\r\n MV.putMVar mvar2 ()\r\n putStrLn \"after putMVar\"\r\n MV.readMVar mvar2 `E.catch` errorHandler2\r\n putStrLn \"after readMVar\"\r\n CC.threadDelay 5000000\r\n where\r\n errorHandler1 :: E.BlockedIndefinitelyOnMVar -> IO ()\r\n errorHandler1 e = putStrLn $ \"errorHandler1 : \" ++ show e\r\n errorHandler2 :: E.BlockedIndefinitelyOnMVar -> IO ()\r\n errorHandler2 e = putStrLn $ \"errorHandler2 : \" ++ show e\r\n}}}\r\n\r\nSave above as \"mvar.hs\" and run by ghc as below.\r\n\r\n{{{\r\n> runhaskell mvar.hs\r\nerrorHandler1 : thread blocked indefinitely in an MVar operation\r\nerrorHandler2 : thread blocked indefinitely in an MVar operation\r\nafter error catch\r\nafter readMVar\r\nafter putMVar\r\n}}}\r\n\r\nBlockedIndefinitelyOnMVar thrown for mvar1 is correct. It will be caught by errorHandler1 and \"threadB\" can continue to put the value to mvar2. It means that \"threadA\" can wait for the value of mvar2 and it is not blocked indefinately.\r\nHowever, BlockedIndefinitelyOnMVar is thrown for mvar2 on \"threadA\" before \"threadB\" puts value to the mvar2. I think it is incorrect.\r\n\r\n----\r\n\r\nI tested another case that adding \"CC.threadDelay 10000000\" before \"readMVar\" as below.\r\n\r\n{{{#!hs\r\nmodule Main where\r\n\r\nimport qualified Control.Concurrent.MVar as MV\r\nimport qualified Control.Concurrent as CC\r\nimport qualified Control.Exception as E\r\n\r\nmain :: IO ()\r\nmain = do\r\n -- call this thread \"threadA\"\r\n mvar1 <- MV.newEmptyMVar :: IO (MV.MVar ())\r\n mvar2 <- MV.newEmptyMVar :: IO (MV.MVar ())\r\n _ <- CC.forkIO $ do\r\n -- call this thread \"threadB\"\r\n MV.takeMVar mvar1 `E.catch` errorHandler1\r\n putStrLn \"after error catch\"\r\n CC.threadDelay 1000000\r\n MV.putMVar mvar2 ()\r\n putStrLn \"after putMVar\"\r\n CC.threadDelay 10000000 -- <-- this line is added\r\n MV.readMVar mvar2 `E.catch` errorHandler2\r\n putStrLn \"after readMVar\"\r\n CC.threadDelay 5000000\r\n where\r\n errorHandler1 :: E.BlockedIndefinitelyOnMVar -> IO ()\r\n errorHandler1 e = putStrLn $ \"errorHandler1 : \" ++ show e\r\n errorHandler2 :: E.BlockedIndefinitelyOnMVar -> IO ()\r\n errorHandler2 e = putStrLn $ \"errorHandler2 : \" ++ show e\r\n}}}\r\n\r\nAnd it will run correctly (BlockedIndefinitelyOnMVar is not thrown for mvar2).\r\n\r\n{{{\r\n> runhaskell mvar.hs\r\nerrorHandler1 : thread blocked indefinitely in an MVar operation\r\nafter error catch\r\nafter putMVar\r\nafter readMVar\r\n}}}\r\n\r\n----\r\n\r\nI found this behavior is same on STM / BlockedIndefinitelyOnSTM.\r\n\r\n{{{#!hs\r\nmodule Main where\r\n\r\nimport qualified Control.Concurrent.STM as STM\r\nimport qualified Control.Concurrent as CC\r\nimport qualified Control.Exception as E\r\n\r\nmain :: IO ()\r\nmain = do\r\n tmv1 <- STM.newEmptyTMVarIO :: IO (STM.TMVar ())\r\n tmv2 <- STM.newEmptyTMVarIO :: IO (STM.TMVar ())\r\n _ <- CC.forkIO $ do\r\n STM.atomically (STM.takeTMVar tmv1) `E.catch` errorHandler1\r\n putStrLn \"after error catch\"\r\n CC.threadDelay 1000000\r\n STM.atomically $ STM.putTMVar tmv2 ()\r\n putStrLn \"after putTMVar\"\r\n STM.atomically (STM.readTMVar tmv2) `E.catch` errorHandler2\r\n putStrLn \"after readTMVar\"\r\n CC.threadDelay 5000000\r\n where\r\n errorHandler1 :: E.BlockedIndefinitelyOnSTM -> IO ()\r\n errorHandler1 e = putStrLn $ \"errorHandler1 : \" ++ show e\r\n errorHandler2 :: E.BlockedIndefinitelyOnSTM -> IO ()\r\n errorHandler2 e = putStrLn $ \"errorHandler2 : \" ++ show e\r\n}}}\r\n\r\n{{{\r\n> runhaskell stm.hs\r\nerrorHandler1 : thread blocked indefinitely in an STM transaction\r\nerrorHandler2 : thread blocked indefinitely in an STM transaction\r\nafter error catch\r\nafter readTMVar\r\nafter putTMVar\r\n}}}\r\n\r\n----\r\n\r\nI tested this in below versions/OSs and got same result (exception thrown for mvar2/tmv2).\r\n\r\nghc7.8.3 on Windows7\r\nghc7.8.3 on lubuntu14.04 on VirtualBox on Windows7\r\nghc7.8.4 on lubuntu14.04 on VirtualBox on Windows7\r\nghc7.10.1 on lubuntu14.04 on VirtualBox on Windows7\r\n\r\nSimilar report https://ghc.haskell.org/trac/ghc/ticket/8804 found but not the same.\r\n(In this case, the reference to the MVar is not weak)\r\n","type_of_failure":"OtherFailure","blocking":[]} -->
issue