reaping fd's and flushing buffers

Simon Marlow
Mon, 6 Jan 2003 14:02:13 -0000

> Sure enough, after I say that all my fd reaping issues are solved at
> the Haskell level, I've been bitten by issues that look like the RTS
> doing things behind my back wrt. reaping fd's etc. etc.
> Basically, while I used socketToHandle the fd's got closed=20
> prematurely,
> and once I eliminated all uses of it, the socket fd's appeared to leak
> despite attempts to explicitly close them.
> Also, there were some very strange goings-on with respect to attempts
> to flush buffers after the fd's they were being flushed to=20
> were closed.
> So, what are the semantics here?

I wouldn't rule out a bug here.  Sockets are actually implemented as two
independent handles internally, one each for the read side and write
side so that each side gets a separate buffer and duplex reading/writing
from different threads is supported.  The programmer still just sees a
single Handle.

The tricky bit is knowing when the socket can be closed: both sides have
to be unreferenced by the program.  We handle this by having the read
side point to the write side, and then place the finalizer on the write
side.  The finalizer should then only run when both sides are
unreferenced (of course, it's always better to do the closing explicitly
if you can).

... actually I've just looked at the code and it looks wrong, aargh!
The finalizer is attached to the wrong side.  If you have a source tree
handy, try changing the following line in libraries/base/GHC/Handle.hs:

 addMVarFinalizer read_side (handleFinalizer read_side)


 addMVarFinalizer write_side (handleFinalizer write_side)