
Hello cafe, I'm currently trying to understand Haskell's threading model and GHC's implementation of it. Specifically I wondered about the safety of file IO. Consider this piece of code:
newtype Socket = Socket (MVar Fd)
read :: Socket -> IO ByteString read (Socket mfd) = do fd <- readMVar mfd -- (1) threadWaitRead fd -- (2) withMVar mfd $ \fd'-> do -- (3) the actual read...
Context: - The socket is configured non-blocking. - No other operation will hold the MVar over a blocking call (because this would make it impossible to close it while it's blocking). - My close operation will fill the MVar with -1 after it's closed and will hold the MVar during the close operation. Questions: - Is it theoretically possible that my thread gets paused at (1) or within threadWaitRead, another thread closes the socket (or even worse opens another file with the same fd) _and_ my thread is resumed afterwards (I'm not asking about async exceptions)? - What constructs contain safepoints and which are guaranteed to be executed without interruption? Considerations (so far): - It is unlikely that (1) is a safepoint as no memory allocations occur, but is it guaranteed? - If the socket were closed during (1), threadWaitRead throws an exception complaining about a bad file descriptor which is unexpected but not harmful. - I found this thread (https://mail.haskell.org/pipermail/haskell-cafe/2014-September/115841.html) which is somewhat related, but I couldn't extract a clear answer from it. Best, Lars