readRawBufferPtr cannot be interrupted by exception on Windows with -threaded
On Windows, in a program compiled with -threaded, if a thread receives from a Handle created by the network package (e.g. with hGetLine), it cannot be interrupted by an asynchronous exception.
I've traced it down to readRawBufferPtr, which is used by Network.Socket.recv. Although I haven't tested readRawBufferPtr directly, my test case (attached) tests Network.Socket.recv.
For Windows, base 4.4.1.0 implements it as:
```
readRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
readRawBufferPtr loc !fd buf off len
| threaded = blockingReadRawBufferPtr loc fd buf off len
| otherwise = asyncReadRawBufferPtr loc fd buf off len
...
blockingReadRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
blockingReadRawBufferPtr loc fd buf off len
= fmap fromIntegral $ throwErrnoIfMinus1Retry loc $
if fdIsSocket fd
then c_safe_recv (fdFD fd) (buf `plusPtr` off) len 0
else c_safe_read (fdFD fd) (buf `plusPtr` off) len
...
-- NOTE: "safe" versions of the read/write calls for use by the threaded RTS.
-- These calls may block, but that's ok.
foreign import stdcall safe "recv"
c_safe_recv :: CInt -> Ptr Word8 -> CSize -> CInt{-flags-} -> IO CSsize
foreign import stdcall safe "send"
c_safe_send :: CInt -> Ptr Word8 -> CSize -> CInt{-flags-} -> IO CSsize
```
If I understand correctly, safe foreign calls cannot be interrupted by asynchronous exceptions.
Is this a bug in readRawBufferPtr, or a bug in the network package? Can a caller expect readRawBufferPtr to be interruptible by an exception?
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.2.2 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries/base |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"readRawBufferPtr cannot be interrupted by exception on Windows with -threaded","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.2.2","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"On Windows, in a program compiled with -threaded, if a thread receives from a Handle created by the network package (e.g. with hGetLine), it cannot be interrupted by an asynchronous exception.\r\n\r\nI've traced it down to readRawBufferPtr, which is used by Network.Socket.recv. Although I haven't tested readRawBufferPtr directly, my test case (attached) tests Network.Socket.recv.\r\n\r\nFor Windows, base 4.4.1.0 implements it as:\r\n\r\n{{{\r\nreadRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt\r\nreadRawBufferPtr loc !fd buf off len\r\n | threaded = blockingReadRawBufferPtr loc fd buf off len\r\n | otherwise = asyncReadRawBufferPtr loc fd buf off len\r\n\r\n...\r\n\r\nblockingReadRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt\r\nblockingReadRawBufferPtr loc fd buf off len\r\n = fmap fromIntegral $ throwErrnoIfMinus1Retry loc $\r\n if fdIsSocket fd\r\n then c_safe_recv (fdFD fd) (buf `plusPtr` off) len 0\r\n else c_safe_read (fdFD fd) (buf `plusPtr` off) len\r\n\r\n...\r\n\r\n-- NOTE: \"safe\" versions of the read/write calls for use by the threaded RTS.\r\n-- These calls may block, but that's ok.\r\n\r\nforeign import stdcall safe \"recv\"\r\n c_safe_recv :: CInt -> Ptr Word8 -> CSize -> CInt{-flags-} -> IO CSsize\r\n\r\nforeign import stdcall safe \"send\"\r\n c_safe_send :: CInt -> Ptr Word8 -> CSize -> CInt{-flags-} -> IO CSsize\r\n}}}\r\n\r\nIf I understand correctly, safe foreign calls cannot be interrupted by asynchronous exceptions.\r\n\r\nIs this a bug in readRawBufferPtr, or a bug in the network package? Can a caller expect readRawBufferPtr to be interruptible by an exception?","type_of_failure":"OtherFailure","blocking":[]} -->
issue