From what I learned about all the subtleties of Haskell's threading and exceptions in the last days I think that the following snippet taken from Network.Socket is unsafe.
socket family stype protocol = do
c_stype <- packSocketTypeOrThrow "socket" stype -- (1)
fd <- throwSocketErrorIfMinus1Retry "socket" $
c_socket (packFamily family) c_stype protocol
setNonBlockIfNeeded fd
socket_status <- newMVar NotConnected -- (2)
withSocketsDo $ return ()
let sock = MkSocket fd family stype protocol socket_status
...
return sock -- (3)
An asynchronous exception may kick in at any safe point (unless it is masked). I would assume that at least (2) is a safe point. If an exception occurs in between (1) and (3) we are in a state where a file descriptor resource has been acquired but has no handle anymore and cannot be released. We're irrevocably leaking a file descriptor here.
From what I learned about all the subtleties of Haskell's threading and exceptions in the last days I think that the following snippet taken from
Network.Socketis unsafe.An asynchronous exception may kick in at any safe point (unless it is masked). I would assume that at least
(2)is a safe point. If an exception occurs in between(1)and(3)we are in a state where a file descriptor resource has been acquired but has no handle anymore and cannot be released. We're irrevocably leaking a file descriptor here.