[GHC] #8804: BlockedIndefinitelyOnMVar thrown for an MVar which is still weakly accessible from another thread

#8804: BlockedIndefinitelyOnMVar thrown for an MVar which is still weakly accessible from another thread --------------------------+------------------------------------------------ Reporter: bholst | Owner: simonmar Type: bug | Status: new Priority: normal | Milestone: Component: | Version: 7.6.3 Runtime System | Operating System: Unknown/Multiple Keywords: | Type of failure: Incorrect result at runtime Architecture: | Test Case: Unknown/Multiple | Blocking: Difficulty: | Unknown | Blocked By: | Related Tickets: | --------------------------+------------------------------------------------ GHC's runtime system throws a BlockedIndefinatelyOnMVar exception when the thread blocking an the MVar is the only one having a direct access to it. It assumes that there will be nothing written into the MVar in the future. This would be the correct behaviour if there were no weak references. The runtime system even throws the Exception when another thread still has a weak reference to the MVar. Consider the following example: {{{ import Control.Concurrent import System.Mem.Weak import Data.Maybe import Control.Monad main = do m <- newEmptyMVar w <- mkWeakMVar m (return ()) forkIO $ do threadDelay 1000000 n <- deRefWeak w when (isJust n) $ putMVar (fromJust n) () takeMVar m }}} At the time of ''takeMVar'' the forked thread has a weak reference to the MVar and it will put a value in it. However, the runtime system throws the Exception: {{{ % ghc BlockingOnMVar.hs -threaded Linking BlockingOnMVar ... % ./BlockingOnMVar +RTS -N2 BlockingOnMVar: thread blocked indefinitely in an MVar operation }}} -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8804 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8804: BlockedIndefinitelyOnMVar thrown for an MVar which is still weakly accessible from another thread ------------------------------------------------+-------------------------- Reporter: bholst | Owner: Type: bug | simonmar Priority: normal | Status: closed Component: Runtime System | Milestone: Resolution: invalid | Version: 7.6.3 Operating System: Unknown/Multiple | Keywords: Type of failure: Incorrect result at runtime | Architecture: Test Case: | Unknown/Multiple Blocking: | Difficulty: | Unknown | Blocked By: | Related Tickets: ------------------------------------------------+-------------------------- Changes (by simonmar): * status: new => closed * resolution: => invalid Comment: This is correct: remember that the weak reference is ''weak'', so it doesn't keep the `MVar` alive, and hence the thread is also not reachable. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8804#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8804: BlockedIndefinitelyOnMVar thrown for an MVar which is still weakly accessible from another thread ------------------------------------------------+-------------------------- Reporter: bholst | Owner: Type: bug | simonmar Priority: normal | Status: closed Component: Runtime System | Milestone: Resolution: invalid | Version: 7.6.3 Operating System: Unknown/Multiple | Keywords: Type of failure: Incorrect result at runtime | Architecture: Test Case: | Unknown/Multiple Blocking: | Difficulty: | Unknown | Blocked By: | Related Tickets: ------------------------------------------------+-------------------------- Comment (by bholst): You mean the waiting thread is garbage collected in this example and that's why the MVar will never be filled? Then keeping the thread reachable through another MVar should do the trick? {{{ import Control.Concurrent import System.Mem.Weak import Data.Maybe import Control.Monad main = do my <- myThreadId m <- newEmptyMVar w <- mkWeakMVar m (return ()) o <- newEmptyMVar _ <- forkIO $ do threadDelay 1000000 n <- deRefWeak w when (isJust n) $ putMVar (fromJust n) () putMVar o () takeMVar m takeMVar o }}} This program has exactly the same output. I understand that the ''MVar m'' is not reachable from the other thread, but nevertheless the main thread is not blocked indefinately on this MVar. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8804#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8804: BlockedIndefinitelyOnMVar thrown for an MVar which is still weakly accessible from another thread ------------------------------------------------+-------------------------- Reporter: bholst | Owner: Type: bug | simonmar Priority: normal | Status: closed Component: Runtime System | Milestone: Resolution: invalid | Version: 7.6.3 Operating System: Unknown/Multiple | Keywords: Type of failure: Incorrect result at runtime | Architecture: Test Case: | Unknown/Multiple Blocking: | Difficulty: | Unknown | Blocked By: | Related Tickets: ------------------------------------------------+-------------------------- Comment (by ezyang): I suspect you typoed, because `my` becomes dead immediately in your code. An MVar will not keep a thread alive unless the thread is blocked on it. If you force the thread to be live it will not get the exception raised, since the thread now retains the MVar. {{{ import Control.Concurrent import System.Mem.Weak import Data.Maybe import Control.Monad import Foreign.StablePtr main = do my <- myThreadId newStablePtr my m <- newEmptyMVar w <- mkWeakMVar m (return ()) _ <- forkIO $ do threadDelay 1000000 n <- deRefWeak w when (isJust n) $ putMVar (fromJust n) () takeMVar m }}} -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8804#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC