Weak pointer to MVar is finalized, even though MVar is still accessible
I'm seeing a problem mixing MVar and Weak: even though the MVar is still accessible from a function's scope (and the main thread is blocking on it), the Weak thinks it should be finalized.
Only seems to happen when compiled with -O2.
Platform: 64-bit Linux Reproduced with GHC versions: 6.10.4, 6.12.3, 7.0.4, 7.2.2, 7.4.1
module Main (main) where
import Control.Concurrent
import Control.Monad (forever, forM_)
import Data.IORef
import System.Mem
import System.Mem.Weak
dispatchPendingCalls :: IORef [Weak (MVar ())] -> IO ()
dispatchPendingCalls ref = forever $ do
threadDelay 100000
pending <- atomicModifyIORef ref (\p -> ([], p))
forM_ pending (\weak -> do
maybeMVar <- deRefWeak weak
case maybeMVar of
Just mvar -> putMVar mvar ()
Nothing -> putStrLn "dispatchReply: weak mvar is Nothing")
call :: IORef [Weak (MVar ())] -> IO ()
call ref = do
mvar <- newEmptyMVar
weak <- mkWeakPtr mvar (Just (putStrLn "call: finalising weak"))
putStrLn "call: about to insert weak into list"
atomicModifyIORef ref (\p -> (weak : p, ()))
putStrLn "call: inserted weak into list"
performGC
takeMVar mvar
putStrLn "call: took from mvar"
main :: IO ()
main = do
pendingCalls <- newIORef []
_ <- forkIO (dispatchPendingCalls pendingCalls)
call pendingCalls
Expected output:
$ ghc --make WeakVar.hs
$ ./WeakMvar
call: about to insert weak into list
call: inserted weak into list
call: took from mvar
Actual output:
$ ghc --make -O2 WeakVar.hs
$ ./WeakMvar
call: about to insert weak into list
call: inserted weak into list
call: finalizing weak
dispatchReply: weak mvar is Nothing
Trac metadata
| Trac field | Value |
|---|---|
| Version | 7.4.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture |