diff options
author | Bruce Korb <bkorb@gnu.org> | 2011-05-06 08:15:59 -0700 |
---|---|---|
committer | Bruce Korb <bkorb@gnu.org> | 2011-05-06 08:15:59 -0700 |
commit | 10c1e9dc30730133dbb631c9be0a4e84ce0b0eaa (patch) | |
tree | c1ecc41b19fbec4e92c119d5cba945b8b91ac7d7 /lib/stdio-write.c | |
parent | 9bccf2c3e4f68a37499615fddd51c727d6bb2624 (diff) | |
parent | d801cb77b966678e21af7a106b15a3fe598d5ec4 (diff) | |
download | gnulib-topic/libposix.tar.gz |
manual mergetopic/libposix
Diffstat (limited to 'lib/stdio-write.c')
-rw-r--r-- | lib/stdio-write.c | 76 |
1 files changed, 62 insertions, 14 deletions
diff --git a/lib/stdio-write.c b/lib/stdio-write.c index 10fcfba9e3..a586c35120 100644 --- a/lib/stdio-write.c +++ b/lib/stdio-write.c @@ -20,8 +20,9 @@ /* Specification. */ #include <stdio.h> -/* Replace these functions only if module 'sigpipe' is requested. */ -#if GNULIB_SIGPIPE +/* Replace these functions only if module 'nonblocking' or module 'sigpipe' is + requested. */ +#if GNULIB_NONBLOCKING || GNULIB_SIGPIPE /* On native Windows platforms, SIGPIPE does not exist. When write() is called on a pipe with no readers, WriteFile() fails with error @@ -38,26 +39,73 @@ # define WIN32_LEAN_AND_MEAN /* avoid including junk */ # include <windows.h> +# if GNULIB_NONBLOCKING +# define CLEAR_ERRNO \ + errno = 0; +# define HANDLE_ENOSPC \ + if (errno == ENOSPC && ferror (stream)) \ + { \ + int fd = fileno (stream); \ + if (fd >= 0) \ + { \ + HANDLE h = (HANDLE) _get_osfhandle (fd); \ + if (GetFileType (h) == FILE_TYPE_PIPE) \ + { \ + /* h is a pipe or socket. */ \ + DWORD state; \ + if (GetNamedPipeHandleState (h, &state, NULL, NULL, \ + NULL, NULL, 0) \ + && (state & PIPE_NOWAIT) != 0) \ + /* h is a pipe in non-blocking mode. \ + Change errno from ENOSPC to EAGAIN. */ \ + errno = EAGAIN; \ + } \ + } \ + } \ + else +# else +# define CLEAR_ERRNO +# define HANDLE_ENOSPC +# endif + +# if GNULIB_SIGPIPE +# define CLEAR_LastError \ + SetLastError (0); +# define HANDLE_ERROR_NO_DATA \ + if (GetLastError () == ERROR_NO_DATA && ferror (stream)) \ + { \ + int fd = fileno (stream); \ + if (fd >= 0 \ + && GetFileType ((HANDLE) _get_osfhandle (fd)) \ + == FILE_TYPE_PIPE) \ + { \ + /* Try to raise signal SIGPIPE. */ \ + raise (SIGPIPE); \ + /* If it is currently blocked or ignored, change errno from \ + EINVAL to EPIPE. */ \ + errno = EPIPE; \ + } \ + } \ + else +# else +# define CLEAR_LastError +# define HANDLE_ERROR_NO_DATA +# endif + # define CALL_WITH_SIGPIPE_EMULATION(RETTYPE, EXPRESSION, FAILED) \ if (ferror (stream)) \ return (EXPRESSION); \ else \ { \ RETTYPE ret; \ - SetLastError (0); \ + CLEAR_ERRNO \ + CLEAR_LastError \ ret = (EXPRESSION); \ - if (FAILED && GetLastError () == ERROR_NO_DATA && ferror (stream)) \ + if (FAILED) \ { \ - int fd = fileno (stream); \ - if (fd >= 0 \ - && GetFileType ((HANDLE) _get_osfhandle (fd)) == FILE_TYPE_PIPE)\ - { \ - /* Try to raise signal SIGPIPE. */ \ - raise (SIGPIPE); \ - /* If it is currently blocked or ignored, change errno from \ - EINVAL to EPIPE. */ \ - errno = EPIPE; \ - } \ + HANDLE_ENOSPC \ + HANDLE_ERROR_NO_DATA \ + ; \ } \ return ret; \ } |