[Haskell-cafe] addFinalizer in GHC 7.10

Viktor Dukhovni ietf-dane at dukhovni.org
Tue Jan 30 22:09:45 UTC 2018



> On Jan 30, 2018, at 4:50 PM, Edward Kmett <ekmett at gmail.com> wrote:
> 
> It would be much, much safer to attach the finalizer to something that has a "presence" all its own, like Weak# () as is done in ForeignPtr. This would result in something like:
> 
> data Socket = Socket !CInt (Weak# ())
> 
> Then when it gets unpacked into another data constructor, then the Weak# () still exists. This isn't free, it comes at the cost that your sockets take a couple of words each (plus finalizer space), but the approach you are taking now isn't free either as it isn't really sound. ;)
> 
> tl;dr don't attach finalizers to regular Haskell data types if you can help it

THanks, good to know.  I gather the unpacking can/will happen even if
Socket internals are [made] opaque to other modules?

And of course in this case, in addition to avoiding
running the finalizer too early, it is critical that each socket be closed
at most once.  Therefore, to support finalization, and make the API safe
for multiple close (as seems to be the case with System.IO Handle's for
example) there's a need for additional mutable state in the Socket, to
keep track of whether it has or has not yet been closed.

I am curious as to what your suggestion would be as to how to best keep
track of such state.

   1. Employ a separate MVar to keep track of socket state, and update
      it on close to ensure at most once close.

   2. Wrap the file descriptor in an IORef, and set it to an invalid
      value (-1 on Unix, INVALID_SOCKET on Windows) on close.  This
      avoids misuse not only with close, but also with attempts at
      read/write/... I/O after close.  However it does not avoid
      (far less likely I think) races to close the socket from
      multiple threads.

   3. Move the state to a wrapper structure managed in FFI code
      so that all socket operations are via a foreign pointer to
      a C-structure in which the file descriptor is invalidated on
      close.

   4.  Other suggestions...

-- 
	Viktor.



More information about the Haskell-Cafe mailing list