[commit: ghc] master: Add a test for #11108 (ba3e1fd)

git at git.haskell.org git at git.haskell.org
Wed May 18 20:00:05 UTC 2016


Repository : ssh://git@git.haskell.org/ghc

On branch  : master
Link       : http://ghc.haskell.org/trac/ghc/changeset/ba3e1fd37dc5004c4307ed205f6701b16faceb59/ghc

>---------------------------------------------------------------

commit ba3e1fd37dc5004c4307ed205f6701b16faceb59
Author: Ben Gamari <ben at smart-cactus.org>
Date:   Tue May 17 19:03:16 2016 +0200

    Add a test for #11108
    
    Reviewers: austin, simonmar, bgamari
    
    Reviewed By: bgamari
    
    Subscribers: thomie
    
    Differential Revision: https://phabricator.haskell.org/D2196
    
    GHC Trac Issues: #11108


>---------------------------------------------------------------

ba3e1fd37dc5004c4307ed205f6701b16faceb59
 testsuite/tests/rts/T11108.hs | 77 +++++++++++++++++++++++++++++++++++++++++++
 testsuite/tests/rts/all.T     |  2 ++
 2 files changed, 79 insertions(+)

diff --git a/testsuite/tests/rts/T11108.hs b/testsuite/tests/rts/T11108.hs
new file mode 100644
index 0000000..d70f333
--- /dev/null
+++ b/testsuite/tests/rts/T11108.hs
@@ -0,0 +1,77 @@
+{-# LANGUAGE RecursiveDo, LambdaCase #-}
+
+import Control.Monad.Fix
+import Data.IORef
+import System.Mem.Weak
+import System.Mem
+
+import Control.Monad
+import Data.Foldable
+
+data Pull = Pull
+  { weakSelf  :: Weak Pull
+  , compute :: Weak Pull -> IO Int
+  , invalidators :: IORef [Weak Pull]
+  , cached  :: IORef (Maybe Int)
+  }
+
+
+makePull :: (Weak Pull -> IO Int) -> IO Pull
+makePull f = do
+  rec
+    -- This seems to be the culprit, changing the order makes the weakRef get gc'ed
+    -- In this configuration it crashes
+
+    foo <- Pull weak f <$> newIORef [] <*> newIORef Nothing
+    weak <- mkWeakPtr foo (Just $ print "died")
+
+  return foo
+
+
+invalidate :: Pull -> IO ()
+invalidate p = do
+  writeIORef (cached p) Nothing
+  invs <- readIORef (invalidators p)
+  writeIORef (invalidators p) []
+  traverse_ (deRefWeak >=> traverse_ invalidate) invs
+
+
+pull :: Weak Pull -> Pull -> IO Int
+pull weak p = do
+  modifyIORef (invalidators p) (weak :)
+  pull' p
+
+pull' :: Pull -> IO Int
+pull' p = do
+  readIORef (cached p) >>= \case
+    Nothing -> do
+      r <- compute p (weakSelf p)
+      writeIORef (cached p) (Just r)
+      return r
+
+    Just r -> return r
+
+add :: Pull -> Int -> IO (Pull)
+add p n = makePull (\w -> (+n) <$> pull w p)
+
+main = do
+  h <- newIORef 0
+
+  source <- makePull (const $ readIORef h)
+  p <- foldM add source (take 1000 (repeat 1))   -- 100 is not enough for crash
+
+  forM_ [1..10] $ \i -> do
+
+    writeIORef h i
+    invalidate source -- Crashes here on second iteration
+
+    --performGC
+    -- This avoids the crash
+
+    print =<< pull' p
+
+
+
+
+
+
diff --git a/testsuite/tests/rts/all.T b/testsuite/tests/rts/all.T
index 720ebfb..d462e39 100644
--- a/testsuite/tests/rts/all.T
+++ b/testsuite/tests/rts/all.T
@@ -260,6 +260,8 @@ test('T9078', [ omit_ways(threaded_ways) ], compile_and_run, ['-with-rtsopts="-D
 test('T10017', [ when(opsys('mingw32'), skip)
                , only_ways(threaded_ways), extra_run_opts('+RTS -N2 -RTS') ], compile_and_run, [''])
 
+test('T11108', normal, compile_and_run, [''])
+
 test('rdynamic', [ unless(opsys('linux') or opsys('mingw32'), skip)
                  # this needs runtime infrastructure to do in ghci:
                  #  '-rdynamic' ghc, load modules only via dlopen(RTLD_BLOBAL) and more.



More information about the ghc-commits mailing list