bug-gnulib
[Top][All Lists]
Advanced

[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>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]