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