I've fixed the 'nonblocking' unit test for pipes now, so that it succeeds on all Unix platforms except Cygwin.
On mingw, I've got two failures, though. The first one is because write() on a non-blocking pipe sets errno to ENOSPC instead of EAGAIN. $ ./test-nonblocking-pipe-main.exe ./test-nonblocking-pipe-child.exe 1 test-nonblocking-pipe-main.c:189: assertion failed This fixes it, by using the same hooks as we already used for handling SIGPIPE. 2011-04-13 Bruno Haible <br...@clisp.org> Support non-blocking pipe I/O in write() on native Windows. * lib/unistd.in.h (write): Enable replacement also if GNULIB_UNISTD_H_NONBLOCKING is 1. * lib/write.c: Enable replacement also if GNULIB_NONBLOCKING. (rpl_write): When failing to write on a non-blocking pipe, change errno from ENOSPC to EAGAIN. * lib/stdio.in.h (fprintf, fputc, fputs, fwrite, printf, putc, putchar, puts, vfprintf, vprintf): Enable replacement also if GNULIB_STDIO_H_NONBLOCKING is 1. * lib/stdio-write.c: Enable replacements also if GNULIB_NONBLOCKING. (CLEAR_ERRNO, HANDLE_ENOSPC): New macros. (CLEAR_LastError, HANDLE_ERROR_NO_DATA): New macros, extracted from CALL_WITH_SIGPIPE_EMULATION. (CALL_WITH_SIGPIPE_EMULATION): Use them. * m4/nonblocking.m4: New file. * m4/write.m4 (gl_FUNC_WRITE): Enable REPLACE_WRITE also if required for non-blocking I/O support. * m4/unistd_h.m4 (gl_UNISTD_H_DEFAULTS): Initialize GNULIB_UNISTD_H_NONBLOCKING. * m4/stdio_h.m4 (gl_STDIO_H): Enable REPLACE_STDIO_WRITE_FUNCS also if required for non-blocking I/O support. (gl_STDIO_H_DEFAULTS): Initialize GNULIB_STDIO_H_NONBLOCKING. * modules/nonblocking (Files): Add m4/nonblocking.m4, lib/stdio-write.c, m4/asm-underscore.m4. (Depends-on): Add stdio, unistd. (configure.ac): Invoke gl_NONBLOCKING_IO. Define GNULIB_NONBLOCKING. Set GNULIB_STDIO_H_NONBLOCKING, GNULIB_UNISTD_H_NONBLOCKING. * modules/unistd (Makefile.am): Substitute GNULIB_UNISTD_H_NONBLOCKING. * modules/stdio (Makefile.am): Substitute GNULIB_STDIO_H_NONBLOCKING. * doc/posix-functions/fprintf.texi: Mention 'nonblocking' module and problem with non-blocking pipes. * doc/posix-functions/fputc.texi: Likewise. * doc/posix-functions/fputs.texi: Likewise. * doc/posix-functions/fwrite.texi: Likewise. * doc/posix-functions/printf.texi: Likewise. * doc/posix-functions/putc.texi: Likewise. * doc/posix-functions/putchar.texi: Likewise. * doc/posix-functions/puts.texi: Likewise. * doc/posix-functions/vfprintf.texi: Likewise. * doc/posix-functions/vprintf.texi: Likewise. * doc/posix-functions/write.texi: Likewise. ============================== m4/nonblocking.m4 ============================== # nonblocking.m4 serial 1 dnl Copyright (C) 2011 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl Tests whether non-blocking I/O is natively supported by read(), write(). dnl Sets gl_cv_have_nonblocking. AC_DEFUN([gl_NONBLOCKING_IO], [ dnl Use AC_REQUIRE here, so that the default behavior below is expanded dnl once only, before all statements that occur in other macros. AC_REQUIRE([gl_NONBLOCKING_IO_BODY]) ]) AC_DEFUN([gl_NONBLOCKING_IO_BODY], [ AC_REQUIRE([AC_CANONICAL_HOST]) case "$host_os" in mingw*) gl_cv_have_nonblocking=no ;; *) gl_cv_have_nonblocking=yes ;; esac ]) =============================================================================== index e922e85..04c4c72 100644 --- a/doc/posix-functions/fprintf.texi +++ b/doc/posix-functions/fprintf.texi @@ -4,7 +4,7 @@ POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/fprintf.html} -Gnulib module: fprintf-posix or stdio, sigpipe +Gnulib module: fprintf-posix or stdio, nonblocking, sigpipe Portability problems fixed by Gnulib module @code{fprintf-posix}: @itemize @@ -64,6 +64,15 @@ This function can crash in out-of-memory conditions on some platforms: MacOS X 10.3, FreeBSD 6.0, NetBSD 5.0. @end itemize +Portability problems fixed by Gnulib module @code{stdio} or @code{fprintf-posix}, together with module @code{nonblocking}: +@itemize +@item +When writing to a non-blocking pipe whose buffer is full, this function fails +with @code{errno} being set to @code{ENOSPC} instead of @code{EAGAIN} on some +platforms: +mingw. +@end itemize + Portability problems fixed by Gnulib module @code{stdio} or @code{fprintf-posix}, together with module @code{sigpipe}: @itemize @item index 2f09a8a..9d6c9fd 100644 --- a/doc/posix-functions/fputc.texi +++ b/doc/posix-functions/fputc.texi @@ -4,9 +4,18 @@ POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/fputc.html} -Gnulib module: stdio, sigpipe +Gnulib module: stdio, nonblocking, sigpipe -Portability problems fixed by Gnulib: +Portability problems fixed by Gnulib module @code{stdio}, together with module @code{nonblocking}: +@itemize +@item +When writing to a non-blocking pipe whose buffer is full, this function fails +with @code{errno} being set to @code{ENOSPC} instead of @code{EAGAIN} on some +platforms: +mingw. +@end itemize + +Portability problems fixed by Gnulib module @code{stdio}, together with module @code{sigpipe}: @itemize @item When writing to a pipe with no readers, this function fails, instead of index d2c46ef..7fc4bf5 100644 --- a/doc/posix-functions/fputs.texi +++ b/doc/posix-functions/fputs.texi @@ -4,9 +4,18 @@ POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/fputs.html} -Gnulib module: stdio, sigpipe +Gnulib module: stdio, nonblocking, sigpipe -Portability problems fixed by Gnulib: +Portability problems fixed by Gnulib module @code{stdio}, together with module @code{nonblocking}: +@itemize +@item +When writing to a non-blocking pipe whose buffer is full, this function fails +with @code{errno} being set to @code{ENOSPC} instead of @code{EAGAIN} on some +platforms: +mingw. +@end itemize + +Portability problems fixed by Gnulib module @code{stdio}, together with module @code{sigpipe}: @itemize @item When writing to a pipe with no readers, this function fails, instead of index d9defec..20f7fb8 100644 --- a/doc/posix-functions/fwrite.texi +++ b/doc/posix-functions/fwrite.texi @@ -4,9 +4,18 @@ POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/fwrite.html} -Gnulib module: stdio, sigpipe +Gnulib module: stdio, nonblocking, sigpipe -Portability problems fixed by Gnulib: +Portability problems fixed by Gnulib module @code{stdio}, together with module @code{nonblocking}: +@itemize +@item +When writing to a non-blocking pipe whose buffer is full, this function fails +with @code{errno} being set to @code{ENOSPC} instead of @code{EAGAIN} on some +platforms: +mingw. +@end itemize + +Portability problems fixed by Gnulib module @code{stdio}, together with module @code{sigpipe}: @itemize @item When writing to a pipe with no readers, this function fails, instead of index eaee96a..df7813f 100644 --- a/doc/posix-functions/printf.texi +++ b/doc/posix-functions/printf.texi @@ -4,7 +4,7 @@ POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/printf.html} -Gnulib module: printf-posix or stdio, sigpipe +Gnulib module: printf-posix or stdio, nonblocking, sigpipe Portability problems fixed by Gnulib module @code{printf-posix}: @itemize @@ -64,6 +64,15 @@ This function can crash in out-of-memory conditions on some platforms: MacOS X 10.3, FreeBSD 6.0, NetBSD 5.0. @end itemize +Portability problems fixed by Gnulib module @code{stdio} or @code{printf-posix}, together with module @code{nonblocking}: +@itemize +@item +When writing to a non-blocking pipe whose buffer is full, this function fails +with @code{errno} being set to @code{ENOSPC} instead of @code{EAGAIN} on some +platforms: +mingw. +@end itemize + Portability problems fixed by Gnulib module @code{stdio} or @code{printf-posix}, together with module @code{sigpipe}: @itemize @item index b7011a0..d156461 100644 --- a/doc/posix-functions/putc.texi +++ b/doc/posix-functions/putc.texi @@ -4,9 +4,18 @@ POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/putc.html} -Gnulib module: stdio, sigpipe +Gnulib module: stdio, nonblocking, sigpipe -Portability problems fixed by Gnulib: +Portability problems fixed by Gnulib module @code{stdio}, together with module @code{nonblocking}: +@itemize +@item +When writing to a non-blocking pipe whose buffer is full, this function fails +with @code{errno} being set to @code{ENOSPC} instead of @code{EAGAIN} on some +platforms: +mingw. +@end itemize + +Portability problems fixed by Gnulib module @code{stdio}, together with module @code{sigpipe}: @itemize @item When writing to a pipe with no readers, this function fails, instead of index d89ab71..aeb6b43 100644 --- a/doc/posix-functions/putchar.texi +++ b/doc/posix-functions/putchar.texi @@ -4,9 +4,18 @@ POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/putchar.html} -Gnulib module: stdio, sigpipe +Gnulib module: stdio, nonblocking, sigpipe -Portability problems fixed by Gnulib: +Portability problems fixed by Gnulib module @code{stdio}, together with module @code{nonblocking}: +@itemize +@item +When writing to a non-blocking pipe whose buffer is full, this function fails +with @code{errno} being set to @code{ENOSPC} instead of @code{EAGAIN} on some +platforms: +mingw. +@end itemize + +Portability problems fixed by Gnulib module @code{stdio}, together with module @code{sigpipe}: @itemize @item When writing to a pipe with no readers, this function fails, instead of index 69ee72e..ef350ac 100644 --- a/doc/posix-functions/puts.texi +++ b/doc/posix-functions/puts.texi @@ -4,9 +4,18 @@ POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/puts.html} -Gnulib module: stdio, sigpipe +Gnulib module: stdio, nonblocking, sigpipe -Portability problems fixed by Gnulib: +Portability problems fixed by Gnulib module @code{stdio}, together with module @code{nonblocking}: +@itemize +@item +When writing to a non-blocking pipe whose buffer is full, this function fails +with @code{errno} being set to @code{ENOSPC} instead of @code{EAGAIN} on some +platforms: +mingw. +@end itemize + +Portability problems fixed by Gnulib module @code{stdio}, together with module @code{sigpipe}: @itemize @item When writing to a pipe with no readers, this function fails, instead of index 7e50234..b40a334 100644 --- a/doc/posix-functions/vfprintf.texi +++ b/doc/posix-functions/vfprintf.texi @@ -4,7 +4,7 @@ POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/vfprintf.html} -Gnulib module: vfprintf-posix or stdio, sigpipe +Gnulib module: vfprintf-posix or stdio, nonblocking, sigpipe Portability problems fixed by Gnulib module @code{vfprintf-posix}: @itemize @@ -64,6 +64,15 @@ This function can crash in out-of-memory conditions on some platforms: MacOS X 10.3, FreeBSD 6.0, NetBSD 5.0. @end itemize +Portability problems fixed by Gnulib module @code{stdio} or @code{vfprintf-posix}, together with module @code{nonblocking}: +@itemize +@item +When writing to a non-blocking pipe whose buffer is full, this function fails +with @code{errno} being set to @code{ENOSPC} instead of @code{EAGAIN} on some +platforms: +mingw. +@end itemize + Portability problems fixed by Gnulib module @code{stdio} or @code{vfprintf-posix}, together with module @code{sigpipe}: @itemize @item index 526070e..342d182 100644 --- a/doc/posix-functions/vprintf.texi +++ b/doc/posix-functions/vprintf.texi @@ -4,7 +4,7 @@ POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/vprintf.html} -Gnulib module: vprintf-posix or stdio, sigpipe +Gnulib module: vprintf-posix or stdio, nonblocking, sigpipe Portability problems fixed by Gnulib module @code{vprintf-posix}: @itemize @@ -64,6 +64,15 @@ This function can crash in out-of-memory conditions on some platforms: MacOS X 10.3, FreeBSD 6.0, NetBSD 5.0. @end itemize +Portability problems fixed by Gnulib module @code{stdio} or @code{vprintf-posix}, together with module @code{nonblocking}: +@itemize +@item +When writing to a non-blocking pipe whose buffer is full, this function fails +with @code{errno} being set to @code{ENOSPC} instead of @code{EAGAIN} on some +platforms: +mingw. +@end itemize + Portability problems fixed by Gnulib module @code{stdio} or @code{vprintf-posix}, together with module @code{sigpipe}: @itemize @item index 826151c..7587fbb 100644 --- a/doc/posix-functions/write.texi +++ b/doc/posix-functions/write.texi @@ -4,9 +4,18 @@ POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/write.html} -Gnulib module: write, sigpipe +Gnulib module: write, nonblocking, sigpipe -Portability problems fixed by Gnulib: +Portability problems fixed by Gnulib module @code{stdio}, together with module @code{nonblocking}: +@itemize +@item +When writing to a non-blocking pipe whose buffer is full, this function fails +with @code{errno} being set to @code{ENOSPC} instead of @code{EAGAIN} on some +platforms: +mingw. +@end itemize + +Portability problems fixed by Gnulib module @code{stdio}, together with module @code{sigpipe}: @itemize @item When writing to a pipe with no readers, this function fails with error --- lib/stdio-write.c.orig Wed Apr 13 12:01:43 2011 +++ lib/stdio-write.c Wed Apr 13 11:59:52 2011 @@ -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; \ } --- lib/stdio.in.h.orig Wed Apr 13 12:01:43 2011 +++ lib/stdio.in.h Wed Apr 13 11:59:52 2011 @@ -203,7 +203,7 @@ #if @GNULIB_FPRINTF_POSIX@ || @GNULIB_FPRINTF@ # if (@GNULIB_FPRINTF_POSIX@ && @REPLACE_FPRINTF@) \ - || (@GNULIB_FPRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@) + || (@GNULIB_FPRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@)) # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # define fprintf rpl_fprintf # endif @@ -262,7 +262,7 @@ #endif #if @GNULIB_FPUTC@ -# if @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef fputc # define fputc rpl_fputc @@ -276,7 +276,7 @@ #endif #if @GNULIB_FPUTS@ -# if @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef fputs # define fputs rpl_fputs @@ -506,7 +506,7 @@ #if @GNULIB_FWRITE@ -# if @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef fwrite # define fwrite rpl_fwrite @@ -711,7 +711,7 @@ #if @GNULIB_PRINTF_POSIX@ || @GNULIB_PRINTF@ # if (@GNULIB_PRINTF_POSIX@ && @REPLACE_PRINTF@) \ - || (@GNULIB_PRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@) + || (@GNULIB_PRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@)) # if defined __GNUC__ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) /* Don't break __attribute__((format(printf,M,N))). */ @@ -760,7 +760,7 @@ #endif #if @GNULIB_PUTC@ -# if @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef putc # define putc rpl_fputc @@ -774,7 +774,7 @@ #endif #if @GNULIB_PUTCHAR@ -# if @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef putchar # define putchar rpl_putchar @@ -788,7 +788,7 @@ #endif #if @GNULIB_PUTS@ -# if @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef puts # define puts rpl_puts @@ -1031,7 +1031,7 @@ #if @GNULIB_VFPRINTF_POSIX@ || @GNULIB_VFPRINTF@ # if (@GNULIB_VFPRINTF_POSIX@ && @REPLACE_VFPRINTF@) \ - || (@GNULIB_VFPRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@) + || (@GNULIB_VFPRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@)) # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # define vfprintf rpl_vfprintf # endif @@ -1067,7 +1067,7 @@ #if @GNULIB_VPRINTF_POSIX@ || @GNULIB_VPRINTF@ # if (@GNULIB_VPRINTF_POSIX@ && @REPLACE_VPRINTF@) \ - || (@GNULIB_VPRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@) + || (@GNULIB_VPRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@)) # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # define vprintf rpl_vprintf # endif --- lib/unistd.in.h.orig Wed Apr 13 12:01:43 2011 +++ lib/unistd.in.h Wed Apr 13 11:59:52 2011 @@ -1359,7 +1359,7 @@ /* Write up to COUNT bytes starting at BUF to file descriptor FD. See the POSIX:2001 specification <http://www.opengroup.org/susv3xsh/write.html>. */ -# if @REPLACE_WRITE@ && @GNULIB_UNISTD_H_SIGPIPE@ +# if @REPLACE_WRITE@ && (@GNULIB_UNISTD_H_NONBLOCKING@ || @GNULIB_UNISTD_H_SIGPIPE@) # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef write # define write rpl_write --- lib/write.c.orig Wed Apr 13 12:01:43 2011 +++ lib/write.c Wed Apr 13 11:59:52 2011 @@ -20,8 +20,9 @@ /* Specification. */ #include <unistd.h> -/* Replace this function only if module 'sigpipe' is requested. */ -#if GNULIB_SIGPIPE +/* Replace this function 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 @@ -45,14 +46,35 @@ if (ret < 0) { - if (GetLastError () == ERROR_NO_DATA - && GetFileType ((HANDLE) _get_osfhandle (fd)) == FILE_TYPE_PIPE) +# if GNULIB_NONBLOCKING + if (errno == ENOSPC) { - /* Try to raise signal SIGPIPE. */ - raise (SIGPIPE); - /* If it is currently blocked or ignored, change errno from EINVAL - to EPIPE. */ - errno = EPIPE; + 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 +# endif + { +# if GNULIB_SIGPIPE + if (GetLastError () == ERROR_NO_DATA + && 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; + } +# endif } } return ret; --- m4/stdio_h.m4.orig Wed Apr 13 12:01:44 2011 +++ m4/stdio_h.m4 Wed Apr 13 11:59:52 2011 @@ -1,4 +1,4 @@ -# stdio_h.m4 serial 33 +# stdio_h.m4 serial 34 dnl Copyright (C) 2007-2011 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -28,9 +28,17 @@ gl_SIGNAL_SIGPIPE if test $gl_cv_header_signal_h_SIGPIPE != yes; then REPLACE_STDIO_WRITE_FUNCS=1 - AC_LIBOBJ([stdio-write]) fi ]) + m4_ifdef([gl_NONBLOCKING_IO], [ + gl_NONBLOCKING_IO + if test $gl_cv_have_nonblocking != yes; then + REPLACE_STDIO_WRITE_FUNCS=1 + fi + ]) + if test $REPLACE_STDIO_WRITE_FUNCS = 1; then + AC_LIBOBJ([stdio-write]) + fi dnl Check for declarations of anything we want to poison if the dnl corresponding gnulib module is not in use, and which is not @@ -82,6 +90,7 @@ GNULIB_RENAMEAT=0; AC_SUBST([GNULIB_RENAMEAT]) GNULIB_SNPRINTF=0; AC_SUBST([GNULIB_SNPRINTF]) GNULIB_SPRINTF_POSIX=0; AC_SUBST([GNULIB_SPRINTF_POSIX]) + GNULIB_STDIO_H_NONBLOCKING=0; AC_SUBST([GNULIB_STDIO_H_NONBLOCKING]) GNULIB_STDIO_H_SIGPIPE=0; AC_SUBST([GNULIB_STDIO_H_SIGPIPE]) GNULIB_TMPFILE=0; AC_SUBST([GNULIB_TMPFILE]) GNULIB_VASPRINTF=0; AC_SUBST([GNULIB_VASPRINTF]) --- m4/unistd_h.m4.orig Wed Apr 13 12:01:44 2011 +++ m4/unistd_h.m4 Wed Apr 13 11:59:52 2011 @@ -1,4 +1,4 @@ -# unistd_h.m4 serial 53 +# unistd_h.m4 serial 54 dnl Copyright (C) 2006-2011 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -52,47 +52,48 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS], [ - GNULIB_CHOWN=0; AC_SUBST([GNULIB_CHOWN]) - GNULIB_CLOSE=0; AC_SUBST([GNULIB_CLOSE]) - GNULIB_DUP2=0; AC_SUBST([GNULIB_DUP2]) - GNULIB_DUP3=0; AC_SUBST([GNULIB_DUP3]) - GNULIB_ENVIRON=0; AC_SUBST([GNULIB_ENVIRON]) - GNULIB_EUIDACCESS=0; AC_SUBST([GNULIB_EUIDACCESS]) - GNULIB_FACCESSAT=0; AC_SUBST([GNULIB_FACCESSAT]) - GNULIB_FCHDIR=0; AC_SUBST([GNULIB_FCHDIR]) - GNULIB_FCHOWNAT=0; AC_SUBST([GNULIB_FCHOWNAT]) - GNULIB_FSYNC=0; AC_SUBST([GNULIB_FSYNC]) - GNULIB_FTRUNCATE=0; AC_SUBST([GNULIB_FTRUNCATE]) - GNULIB_GETCWD=0; AC_SUBST([GNULIB_GETCWD]) - GNULIB_GETDOMAINNAME=0; AC_SUBST([GNULIB_GETDOMAINNAME]) - GNULIB_GETDTABLESIZE=0; AC_SUBST([GNULIB_GETDTABLESIZE]) - GNULIB_GETGROUPS=0; AC_SUBST([GNULIB_GETGROUPS]) - GNULIB_GETHOSTNAME=0; AC_SUBST([GNULIB_GETHOSTNAME]) - GNULIB_GETLOGIN=0; AC_SUBST([GNULIB_GETLOGIN]) - GNULIB_GETLOGIN_R=0; AC_SUBST([GNULIB_GETLOGIN_R]) - GNULIB_GETPAGESIZE=0; AC_SUBST([GNULIB_GETPAGESIZE]) - GNULIB_GETUSERSHELL=0; AC_SUBST([GNULIB_GETUSERSHELL]) - GNULIB_LCHOWN=0; AC_SUBST([GNULIB_LCHOWN]) - GNULIB_LINK=0; AC_SUBST([GNULIB_LINK]) - GNULIB_LINKAT=0; AC_SUBST([GNULIB_LINKAT]) - GNULIB_LSEEK=0; AC_SUBST([GNULIB_LSEEK]) - GNULIB_PIPE=0; AC_SUBST([GNULIB_PIPE]) - GNULIB_PIPE2=0; AC_SUBST([GNULIB_PIPE2]) - GNULIB_PREAD=0; AC_SUBST([GNULIB_PREAD]) - GNULIB_PWRITE=0; AC_SUBST([GNULIB_PWRITE]) - GNULIB_READLINK=0; AC_SUBST([GNULIB_READLINK]) - GNULIB_READLINKAT=0; AC_SUBST([GNULIB_READLINKAT]) - GNULIB_RMDIR=0; AC_SUBST([GNULIB_RMDIR]) - GNULIB_SLEEP=0; AC_SUBST([GNULIB_SLEEP]) - GNULIB_SYMLINK=0; AC_SUBST([GNULIB_SYMLINK]) - GNULIB_SYMLINKAT=0; AC_SUBST([GNULIB_SYMLINKAT]) - GNULIB_TTYNAME_R=0; AC_SUBST([GNULIB_TTYNAME_R]) - GNULIB_UNISTD_H_GETOPT=0; AC_SUBST([GNULIB_UNISTD_H_GETOPT]) - GNULIB_UNISTD_H_SIGPIPE=0; AC_SUBST([GNULIB_UNISTD_H_SIGPIPE]) - GNULIB_UNLINK=0; AC_SUBST([GNULIB_UNLINK]) - GNULIB_UNLINKAT=0; AC_SUBST([GNULIB_UNLINKAT]) - GNULIB_USLEEP=0; AC_SUBST([GNULIB_USLEEP]) - GNULIB_WRITE=0; AC_SUBST([GNULIB_WRITE]) + GNULIB_CHOWN=0; AC_SUBST([GNULIB_CHOWN]) + GNULIB_CLOSE=0; AC_SUBST([GNULIB_CLOSE]) + GNULIB_DUP2=0; AC_SUBST([GNULIB_DUP2]) + GNULIB_DUP3=0; AC_SUBST([GNULIB_DUP3]) + GNULIB_ENVIRON=0; AC_SUBST([GNULIB_ENVIRON]) + GNULIB_EUIDACCESS=0; AC_SUBST([GNULIB_EUIDACCESS]) + GNULIB_FACCESSAT=0; AC_SUBST([GNULIB_FACCESSAT]) + GNULIB_FCHDIR=0; AC_SUBST([GNULIB_FCHDIR]) + GNULIB_FCHOWNAT=0; AC_SUBST([GNULIB_FCHOWNAT]) + GNULIB_FSYNC=0; AC_SUBST([GNULIB_FSYNC]) + GNULIB_FTRUNCATE=0; AC_SUBST([GNULIB_FTRUNCATE]) + GNULIB_GETCWD=0; AC_SUBST([GNULIB_GETCWD]) + GNULIB_GETDOMAINNAME=0; AC_SUBST([GNULIB_GETDOMAINNAME]) + GNULIB_GETDTABLESIZE=0; AC_SUBST([GNULIB_GETDTABLESIZE]) + GNULIB_GETGROUPS=0; AC_SUBST([GNULIB_GETGROUPS]) + GNULIB_GETHOSTNAME=0; AC_SUBST([GNULIB_GETHOSTNAME]) + GNULIB_GETLOGIN=0; AC_SUBST([GNULIB_GETLOGIN]) + GNULIB_GETLOGIN_R=0; AC_SUBST([GNULIB_GETLOGIN_R]) + GNULIB_GETPAGESIZE=0; AC_SUBST([GNULIB_GETPAGESIZE]) + GNULIB_GETUSERSHELL=0; AC_SUBST([GNULIB_GETUSERSHELL]) + GNULIB_LCHOWN=0; AC_SUBST([GNULIB_LCHOWN]) + GNULIB_LINK=0; AC_SUBST([GNULIB_LINK]) + GNULIB_LINKAT=0; AC_SUBST([GNULIB_LINKAT]) + GNULIB_LSEEK=0; AC_SUBST([GNULIB_LSEEK]) + GNULIB_PIPE=0; AC_SUBST([GNULIB_PIPE]) + GNULIB_PIPE2=0; AC_SUBST([GNULIB_PIPE2]) + GNULIB_PREAD=0; AC_SUBST([GNULIB_PREAD]) + GNULIB_PWRITE=0; AC_SUBST([GNULIB_PWRITE]) + GNULIB_READLINK=0; AC_SUBST([GNULIB_READLINK]) + GNULIB_READLINKAT=0; AC_SUBST([GNULIB_READLINKAT]) + GNULIB_RMDIR=0; AC_SUBST([GNULIB_RMDIR]) + GNULIB_SLEEP=0; AC_SUBST([GNULIB_SLEEP]) + GNULIB_SYMLINK=0; AC_SUBST([GNULIB_SYMLINK]) + GNULIB_SYMLINKAT=0; AC_SUBST([GNULIB_SYMLINKAT]) + GNULIB_TTYNAME_R=0; AC_SUBST([GNULIB_TTYNAME_R]) + GNULIB_UNISTD_H_GETOPT=0; AC_SUBST([GNULIB_UNISTD_H_GETOPT]) + GNULIB_UNISTD_H_NONBLOCKING=0; AC_SUBST([GNULIB_UNISTD_H_NONBLOCKING]) + GNULIB_UNISTD_H_SIGPIPE=0; AC_SUBST([GNULIB_UNISTD_H_SIGPIPE]) + GNULIB_UNLINK=0; AC_SUBST([GNULIB_UNLINK]) + GNULIB_UNLINKAT=0; AC_SUBST([GNULIB_UNLINKAT]) + GNULIB_USLEEP=0; AC_SUBST([GNULIB_USLEEP]) + GNULIB_WRITE=0; AC_SUBST([GNULIB_WRITE]) dnl Assume proper GNU behavior unless another module says otherwise. HAVE_CHOWN=1; AC_SUBST([HAVE_CHOWN]) HAVE_DUP2=1; AC_SUBST([HAVE_DUP2]) --- m4/write.m4.orig Wed Apr 13 12:01:44 2011 +++ m4/write.m4 Wed Apr 13 11:59:52 2011 @@ -1,4 +1,4 @@ -# write.m4 serial 1 +# write.m4 serial 2 dnl Copyright (C) 2008-2011 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -14,7 +14,15 @@ gl_SIGNAL_SIGPIPE if test $gl_cv_header_signal_h_SIGPIPE != yes; then REPLACE_WRITE=1 - AC_LIBOBJ([write]) fi ]) + m4_ifdef([gl_NONBLOCKING_IO], [ + gl_NONBLOCKING_IO + if test $gl_cv_have_nonblocking != yes; then + REPLACE_WRITE=1 + fi + ]) + if test $REPLACE_WRITE = 1; then + AC_LIBOBJ([write]) + fi ]) --- modules/nonblocking.orig Wed Apr 13 12:01:44 2011 +++ modules/nonblocking Wed Apr 13 12:01:05 2011 @@ -2,18 +2,33 @@ Read, set or clear the non-blocking file descriptor flag. Files: -lib/nonblocking.c lib/nonblocking.h +lib/nonblocking.c +m4/nonblocking.m4 +lib/stdio-write.c +m4/asm-underscore.m4 Depends-on: fcntl-h ioctl open stdbool +stdio sys_socket +unistd configure.ac: +gl_NONBLOCKING_IO gl_FCNTL_MODULE_INDICATOR([nonblocking]) +dnl Define the C macro GNULIB_NONBLOCKING to 1. +gl_MODULE_INDICATOR([nonblocking]) +dnl Define the substituted variable GNULIB_STDIO_H_NONBLOCKING to 1. +AC_REQUIRE([gl_STDIO_H_DEFAULTS]) +AC_REQUIRE([gl_ASM_SYMBOL_PREFIX]) +GNULIB_STDIO_H_NONBLOCKING=1 +dnl Define the substituted variable GNULIB_UNISTD_H_NONBLOCKING to 1. +AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) +GNULIB_UNISTD_H_NONBLOCKING=1 Makefile.am: lib_SOURCES += nonblocking.c --- modules/stdio.orig Wed Apr 13 12:01:44 2011 +++ modules/stdio Wed Apr 13 11:59:52 2011 @@ -58,6 +58,7 @@ -e 's|@''GNULIB_RENAMEAT''@|$(GNULIB_RENAMEAT)|g' \ -e 's|@''GNULIB_SNPRINTF''@|$(GNULIB_SNPRINTF)|g' \ -e 's|@''GNULIB_SPRINTF_POSIX''@|$(GNULIB_SPRINTF_POSIX)|g' \ + -e 's|@''GNULIB_STDIO_H_NONBLOCKING''@|$(GNULIB_STDIO_H_NONBLOCKING)|g' \ -e 's|@''GNULIB_STDIO_H_SIGPIPE''@|$(GNULIB_STDIO_H_SIGPIPE)|g' \ -e 's|@''GNULIB_TMPFILE''@|$(GNULIB_TMPFILE)|g' \ -e 's|@''GNULIB_VASPRINTF''@|$(GNULIB_VASPRINTF)|g' \ --- modules/unistd.orig Wed Apr 13 12:01:44 2011 +++ modules/unistd Wed Apr 13 11:59:52 2011 @@ -64,6 +64,7 @@ -e 's|@''GNULIB_SYMLINKAT''@|$(GNULIB_SYMLINKAT)|g' \ -e 's|@''GNULIB_TTYNAME_R''@|$(GNULIB_TTYNAME_R)|g' \ -e 's|@''GNULIB_UNISTD_H_GETOPT''@|$(GNULIB_UNISTD_H_GETOPT)|g' \ + -e 's|@''GNULIB_UNISTD_H_NONBLOCKING''@|$(GNULIB_UNISTD_H_NONBLOCKING)|g' \ -e 's|@''GNULIB_UNISTD_H_SIGPIPE''@|$(GNULIB_UNISTD_H_SIGPIPE)|g' \ -e 's|@''GNULIB_UNLINK''@|$(GNULIB_UNLINK)|g' \ -e 's|@''GNULIB_UNLINKAT''@|$(GNULIB_UNLINKAT)|g' \ -- In memoriam Anton Schmid <http://en.wikipedia.org/wiki/Anton_Schmid> <http://www.shoah.dk/Courage/Schmid.htm>