[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
writing to non-blocking pipes on Windows
From: |
Bruno Haible |
Subject: |
writing to non-blocking pipes on Windows |
Date: |
Wed, 13 Apr 2011 12:38:39 +0200 |
User-agent: |
KMail/1.9.9 |
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 <address@hidden>
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}:
address@hidden
address@hidden
+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.
address@hidden 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}:
address@hidden
address@hidden
+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.
address@hidden 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}:
address@hidden
address@hidden
+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.
address@hidden 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}:
address@hidden
address@hidden
+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.
address@hidden 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}:
address@hidden
address@hidden
+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.
address@hidden 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}:
address@hidden
address@hidden
+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.
address@hidden 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}:
address@hidden
address@hidden
+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.
address@hidden 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}:
address@hidden
address@hidden
+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.
address@hidden 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}:
address@hidden
address@hidden
+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.
address@hidden 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}:
address@hidden
address@hidden
+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.
address@hidden 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}:
address@hidden
address@hidden
+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.
address@hidden 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>
- writing to non-blocking pipes on Windows,
Bruno Haible <=