Another possible flaw in the Socket code?

Keean k.schupke@ic.ac.uk
Sun, 6 Apr 2003 20:33:11 +0100


Here are the symptoms, each connection to a server sparks a thread. The
thread does the processing, which may be interrupted by an asynchnonous
exception (sigPIPE) at any point.

Sometimes partially closed sockets are left open, even though the sparked
thread has a finally clause closeing the handle for the socket. This seems
to happen because a write to a socket that has been closed at the write end
causes sigPIPE. If this signal is ignored an asynchronous exception is
delivered to the thread, which causes a thread level exception handler to
try and close the socket.

The problem seems to be the finalizer itself tries to flush the write side,
which results
in an uncought exception meaning c_close is never called, hence the hanging
socket.

Here is a possible fix:


handleFinalizer :: MVar Handle__ -> IO ()
handleFinalizer m = do
  h_ <- takeMVar m
  catch (flushWriteBufferOnly h_) (\e -> return()) -- catch exception if
remote side closed
  let fd = fromIntegral (haFD h_)
  unlockFile fd
  when (fd /= -1)
#ifdef mingw32_TARGET_OS
       (closeFd (haIsStream h_) fd >> return ())
#else
       (c_close fd >> return ())
#endif
  return ()

I think hClose should be modified also, does this sound reasonable?

	Regards,
	Keean Schupke