WriteFile() returns ERROR_NO_DATA when writing to a pipe that is
"closing", however by default the write() wrapper in the CRT maps this
to EINVAL so we get confusing things like
hPutChar: invalid argument (Invalid Argumnet)
when piping the output of a Haskell program into something that closes
the pipe early. This was happening in the testsuite in a few place.
The solution is to map ERROR_NO_DATA to EPIPE correctly, as we
explicitly check for EPIPE on stdout (in GHC.TopHandler) so we can
exit without an error in this case.
= fmap fromIntegral $ throwErrnoIfMinus1Retry loc $
if fdIsSocket fd
then c_safe_send (fdFD fd) (buf `plusPtr` off) len 0
= fmap fromIntegral $ throwErrnoIfMinus1Retry loc $
if fdIsSocket fd
then c_safe_send (fdFD fd) (buf `plusPtr` off) len 0
- else c_safe_write (fdFD fd) (buf `plusPtr` off) len
+ else do
+ r <- c_safe_write (fdFD fd) (buf `plusPtr` off) len
+ when (r == -1) c_maperrno
+ return r
+ -- we don't trust write() to give us the correct errno, and
+ -- instead do the errno conversion from GetLastError()
+ -- ourselves. The main reason is that we treat ERROR_NO_DATA
+ -- (pipe is closing) as EPIPE, whereas write() returns EINVAL
+ -- for this case. We need to detect EPIPE correctly, because it
+ -- shouldn't be reported as an error when it happens on stdout.
+
+foreign import ccall unsafe "maperrno" -- in Win32Utils.c
+ c_maperrno :: IO ()
-- NOTE: "safe" versions of the read/write calls for use by the threaded RTS.
-- These calls may block, but that's ok.
-- NOTE: "safe" versions of the read/write calls for use by the threaded RTS.
-- These calls may block, but that's ok.
{ ERROR_ALREADY_EXISTS, EEXIST }, /* 183 */
{ ERROR_FILENAME_EXCED_RANGE, ENOENT }, /* 206 */
{ ERROR_NESTING_NOT_ALLOWED, EAGAIN }, /* 215 */
{ ERROR_ALREADY_EXISTS, EEXIST }, /* 183 */
{ ERROR_FILENAME_EXCED_RANGE, ENOENT }, /* 206 */
{ ERROR_NESTING_NOT_ALLOWED, EAGAIN }, /* 215 */
- { ERROR_NOT_ENOUGH_QUOTA, ENOMEM } /* 1816 */
+ /* Windows returns this when the read end of a pipe is
+ * closed (or closing) and we write to it. */
+ { ERROR_NO_DATA, EPIPE }, /* 232 */
+ { ERROR_NOT_ENOUGH_QUOTA, ENOMEM } /* 1816 */
};
/* size of the table */
};
/* size of the table */