Finalizers etcetera

Alastair Reid alastair at reid-consulting-uk.ltd.uk
Thu Oct 10 04:04:13 EDT 2002


> Alastair, You didn't respond to my proposal, perhaps because it
> didn't seem like one (I've changed a few words)

Sorry, you're right, it didn't seem like one.  

In fact, even now, I'm not sure exactly what you're proposing. 

Am I right in thinking that you are proposing that we revert to
writing Haskell finalizers but that Hugs and NHC programmers would
have to avoid writing finalizers which manipulate Haskell state while
GHC would use MVars to protect that state?

I see a number of problems with this:

1) It encourages people to write finalizers with race conditions.
   (And, because the race conditions are rare, they won't 
   even know they are doing it.)

2) It encourages slightly more clueful people to write finalizers which
   deadlocks on Hugs.  This is not because Hugs is buggy but because
   Hugs finalizers are not run in a separate thread.

3) It encourages the even more clueful to write code that only works
   on GHC.  They ignore Hugs and NHC assuming that we are just being
   slow to implement the full FFI specification.  Portability suffers.

4) Even the most clueful people might be caught out occasionally if a
   library routine they use happens to manipulate a global variable.

   All it would take is for Hugs to switch over to using GHC's IO
   library (hPutStr and friends) and even something as simple and
   common as using print or trace in a finalizer would be incorrect
   (i.e., cause either deadlock or a race condition).

Only a very few will write code that is correct and portable.

The bugs concern me because the FFI world is already pretty hairy - we
really don't need to add another source of variability.  Especially
one that causes bugs that are so hard to reproduce.

The loss of portability concerns me because it's something I've been
trying to improve pretty much since my days of hacking on Yale Haskell
(i.e., before I got involved in Hugs).


My alternate proposal is this:

   Finalizers are to be written in C.
   Finalizers are subject to the same restrictions as unsafe foreign imports.

   We add hs_freeStablePtr and state that it can be called by unsafe foreign
   imported functions.

   GHC's documentation says that GHC finalizers are subject to the weaker
   restrictions of _safe_ foreign imports.

   Hugs and NHC might consider adding runtime tests to guard against people
   calling unsafe foreign imports which make illegal calls into Haskell.
   (Very easy: set a bit when making safe calls, test the bit on calling back
   into Haskell, pop the bit when safe calls return.)

   We consider relaxing the specification as the GHC experience demonstrates 
   sufficient value and as we find ways for all compilers to implement it.
   (I'm not holding my breath here but if we can make things more flexible
   I'm happy to do so.)

This (i.e., the first 2 paragraphs) is a simple specification.  People
already know what 'unsafe' means because it's used elsewhere in the
ffi spec.

NHC and Hugs can release objects very promptly whether their code
involves the IO monad or not.

It makes it easier to write the finalizer in C than in Haskell so the
default behaviour is to write safe, portable code.

NHC and Hugs can test for violations of the rule.
GHC can provide extensions of the rule.

The ffi specification doesn't contain even the slightest whiff of a
suggestion that finalizers can/should/must be written in Haskell
so people are less likely to write buggy or non-portable code and 
then wonder why it doesn't work, report it as bugs, etc.


--
Alastair



More information about the FFI mailing list