Help me grok addFinalizer

Simon Marlow marlowsd at gmail.com
Fri Feb 17 13:30:52 CET 2012


On 16/02/2012 22:20, Michael Craig wrote:
>  > I haven't checked, but ...
>
> I checked, and your solution works. In the context of a larger program,
> getting NOLINE pragmas in all the right places would be challenging,
> wouldn't it?
>
> I found a bug report on the GHC Trac [1] in which Simon explains the
> importance of evaluating the thunk before calling addFinalizer.
> (Otherwise the finalizer is added to the thunk.) This works:
>
> newThing :: IO Thing
> newThing = do
>    x <- Thing `fmap` newIORef True
>    return $ unsafePerformIO ( do
>      x' <- evaluate x
>      addFinalizer x' $ putStrLn "running finalizer" ) `seq` x
>
> If anyone can show me how to get rid of unsafePerformIO in there, that'd
> be great. Tried a few things to no avail.

If your goal is to add a finalizer to an IORef, I would use 
Data.IORef.mkWeakIORef.  It adds the finalizer to the actual primitive 
MutVar# object inside the IORef, so it's a lot more predictable (the 
primitive object can't be copied under your feet).

>  > Finalizers are tricky things, especially when combined with some of
>>  GHC's optimisations.
>
> No kidding!

Finalizers on ordinary Haskell objects are very limited in usefulness, 
the only good use I've found is for memo tables.

Cheers,
	Simon



>
> [1] http://hackage.haskell.org/trac/ghc/ticket/5365
>
> Mike Craig
>
>
>
> On Thu, Feb 16, 2012 at 4:15 PM, Ian Lynagh <igloo at earth.li
> <mailto:igloo at earth.li>> wrote:
>
>     On Thu, Feb 16, 2012 at 02:55:13PM -0600, Austin Seipp wrote:
>      > 64-bit GHC on OS X gives me this:
>      >
>      > $ ghc -fforce-recomp -threaded finalizer
>      > [1 of 1] Compiling Main             ( finalizer.hs, finalizer.o )
>      > Linking finalizer ...
>      > $ ./finalizer
>      > waiting ...
>      > done!
>      > waiting ...
>      > running finalizer
>      > done!
>      >
>      > However, it's a different story when `-O2` is specified:
>      >
>      > $ ghc -O2 -fforce-recomp -threaded finalizer
>      > [1 of 1] Compiling Main             ( finalizer.hs, finalizer.o )
>      > Linking finalizer ...
>      > $ ./finalizer
>      > waiting ...
>      > running finalizer
>      > done!
>      > waiting ...
>      > done!
>      >
>      > This smells like a bug. The stranger thing is that the GC will
>     run the
>      > finalizer, but it doesn't reclaim the object? I'd think `readIORef`
>      > going after an invalidated pointer the GC reclaimed would almost
>      > certainly crash.
>
>     The finalizer is attached to the Thing, not the IORef. I haven't
>     checked, but I assume that ioref gets inlined, so effectively (ioref x)
>     is evaluated early. If you change it to
>
>         readIORef (ioref' x) >>= \ix -> ix `seq` return ()
>
>     and define
>
>         {-# NOINLINE ioref' #-}
>         ioref' :: Thing -> IORef Bool
>         ioref' = ioref
>
>     then you'll get the sort of output you expect.
>
>     Finalizers are tricky things, especially when combined with some of
>     GHC's optimisations.
>
>
>     Thanks
>     Ian
>
>
>     _______________________________________________
>     Glasgow-haskell-users mailing list
>     Glasgow-haskell-users at haskell.org
>     <mailto:Glasgow-haskell-users at haskell.org>
>     http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
>
>
>
>
> _______________________________________________
> Glasgow-haskell-users mailing list
> Glasgow-haskell-users at haskell.org
> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users




More information about the Glasgow-haskell-users mailing list