[Haskell-cafe] Re: hPutStrLn and hFlush

John Meacham john at repetae.net
Tue Jan 10 15:19:51 EST 2006

On Tue, Jan 10, 2006 at 09:40:41AM +0000, Simon Marlow wrote:
> John Meacham wrote:
> >Yeah. this is a major bug in ghc IMHO. I believe it has been fixed, but
> >am unsure.
> It hasn't been fixed, this is the current behaviour and it's likely to 
> stay that way, I'm afraid.
> We used to run finalizers on exit, but we stopped doing that for various 
> reasons.  Even when we did run finalizers on exit, we couldn't guarantee 
> to run all of them.

oh, the bug I was refering to was not not running finalizers on exit
(which makes sense) but rather not flushing file handles on exit. the
implication being that flushing the file handles should be done via some
other mechanism than the GC finalizer.

> >Since we can't rely on finalizers to run in general, some
> >sort of 'atexit' routine is needed. (which would be a good addition to
> >the standard libraries anyway)
> You can implement atexit quite straightforwardly, if that's what you want.
> exits = unsafePerformIO (newIORef []) :: IORef [IO ()]
> main = do_stuff `finally` (readIORef exits >>= sequence_ . reverse)
> atexit io = modifyIORef exits (io:)

The problem is that people would have to know to put that in main, so
the atexit functionality could not be used from libraries. I am thinking
something more akin to C's atexit(3) function provided by its standard

a proposed interface would be

module System.Exit  -- append to the current System.Exit

data AtExitHandle

-- | add a routine to be called on program exit
addHandle :: IO () -> IO AtExitHandle
-- | remove a routine previously set to be run on program exit, this actios is idempotent.
removeHandle :: AtExitHandle -> IO ()
-- | run and remove a routine atomically, guarenteed to run routine at most once, even if called multiple times
runRemoveHandle :: AtExitHandle -> IO ()

so, hOpen will do an 
addHandle (hClose h) stowing the AtExitHandle and hClose will do a removeHandle on the AtExitHandle

I will happily implement this, I have needed it on several occasions
when working on real-world programs especially since the (correct)
decision to not ensure finalizers are run. (like making sure the terminal mode
is reset, or that certain resources (lock files, SYSV semaphores) are released)

in addition, I would add a _exitWith to System.Exit as the obvious
parallel to _exit(2).


John Meacham - ⑆repetae.net⑆john⑈ 

More information about the Haskell-Cafe mailing list