Mercurial > hg > octave-lojdl > gnulib-hg
changeset 14578:4e83bc0de9e4
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.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Wed, 13 Apr 2011 12:15:43 +0200 |
parents | e970e3400175 |
children | 9e7c988068ce |
files | ChangeLog doc/posix-functions/fprintf.texi doc/posix-functions/fputc.texi doc/posix-functions/fputs.texi doc/posix-functions/fwrite.texi doc/posix-functions/printf.texi doc/posix-functions/putc.texi doc/posix-functions/putchar.texi doc/posix-functions/puts.texi doc/posix-functions/vfprintf.texi doc/posix-functions/vprintf.texi doc/posix-functions/write.texi lib/stdio-write.c lib/stdio.in.h lib/unistd.in.h lib/write.c m4/nonblocking.m4 m4/stdio_h.m4 m4/unistd_h.m4 m4/write.m4 modules/nonblocking modules/stdio modules/unistd |
diffstat | 23 files changed, 370 insertions(+), 99 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,47 @@ +2011-04-13 Bruno Haible <bruno@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. + 2011-04-10 Jim Meyering <meyering@redhat.com> maint.mk: prohibit doubled words
--- 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 @@ 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
--- 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
--- 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
--- 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
--- 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 @@ 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
--- 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
--- 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
--- 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
--- 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 @@ 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
--- 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 @@ 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
--- 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
--- 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; \ }
--- a/lib/stdio.in.h +++ b/lib/stdio.in.h @@ -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
--- a/lib/unistd.in.h +++ b/lib/unistd.in.h @@ -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
--- a/lib/write.c +++ b/lib/write.c @@ -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;
new file mode 100644 --- /dev/null +++ b/m4/nonblocking.m4 @@ -0,0 +1,23 @@ +# 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 +])
--- a/m4/stdio_h.m4 +++ b/m4/stdio_h.m4 @@ -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])
--- a/m4/unistd_h.m4 +++ b/m4/unistd_h.m4 @@ -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])
--- a/m4/write.m4 +++ b/m4/write.m4 @@ -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 ])
--- a/modules/nonblocking +++ b/modules/nonblocking @@ -2,18 +2,33 @@ Read, set or clear the non-blocking file descriptor flag. Files: +lib/nonblocking.h lib/nonblocking.c -lib/nonblocking.h +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
--- a/modules/stdio +++ b/modules/stdio @@ -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' \
--- a/modules/unistd +++ b/modules/unistd @@ -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' \