Help me grok addFinalizer

Michael Craig mkscrg at gmail.com
Thu Feb 16 23:20:42 CET 2012


> 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.

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

No kidding!

[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> 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
> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/glasgow-haskell-users/attachments/20120216/dea2d661/attachment.htm>


More information about the Glasgow-haskell-users mailing list