Commit deea031d authored by Simon Marlow's avatar Simon Marlow
Browse files

Windows: map ERROR_NO_DATA to EPIPE, rather than EINVAL

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.
parent 1b0a5be0
......@@ -582,7 +582,19 @@ blockingWriteRawBufferPtr loc fd buf off len
= 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.
......
......@@ -61,7 +61,10 @@ static struct errentry errtable[] = {
{ 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 */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment