Admin message

Due to a large amount of spam we do not allow new users to create repositories, they are "external" users. If you are a new user and want to create a repository, for example for forking GHC, open a new issue on ghc/ghc using the "get-verified" issue template

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