pipe-filter-ii: Fix test failure on AIX and IRIX.
authorBruno Haible <bruno@clisp.org>
Sun, 5 Jun 2011 17:15:25 +0000 (19:15 +0200)
committerBruno Haible <bruno@clisp.org>
Sun, 5 Jun 2011 17:15:25 +0000 (19:15 +0200)
* lib/pipe-filter-ii.c (pipe_filter_ii_execute): When write() fails
with EAGAIN, retry with a smaller buffer size.

ChangeLog
lib/pipe-filter-ii.c

index f6db6cb1ee5495761f6d7a60997a78278a3e7a88..0262b303e2969768dbf706e094d3c8b14c40b3c9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2011-06-05  Bruno Haible  <bruno@clisp.org>
+
+       pipe-filter-ii: Fix test failure on AIX and IRIX.
+       * lib/pipe-filter-ii.c (pipe_filter_ii_execute): When write() fails
+       with EAGAIN, retry with a smaller buffer size.
+
 2011-06-05  Bruno Haible  <bruno@clisp.org>
 
        localename: Fix link dependencies.
index f20b7b41c58d1938c0f539df6f7ee65ca1b18c20..d0eb86b7766574cf5598e4f640582356944cdb5a 100644 (file)
@@ -347,21 +347,42 @@ pipe_filter_ii_execute (const char *progname,
             const void *buf = prepare_write (&bufsize, private_data);
             if (buf != NULL)
               {
-                ssize_t nwritten =
-                  write (fd[1], buf,
-                         bufsize > SSIZE_MAX ? SSIZE_MAX : bufsize);
-                if (nwritten < 0)
+                /* Writing to a pipe in non-blocking mode is tricky: The
+                   write() call may fail with EAGAIN, simply because suffcient
+                   space is not available in the pipe. See POSIX:2008
+                   <http://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html>.
+                   This happens actually on AIX and IRIX, when bufsize >= 8192
+                   (even though PIPE_BUF and pathconf ("/", _PC_PIPE_BUF) are
+                   both 32768).  */
+                size_t attempt_to_write =
+                  (bufsize > SSIZE_MAX ? SSIZE_MAX : bufsize);
+                for (;;)
                   {
-                    if (!IS_EAGAIN (errno))
+                    ssize_t nwritten = write (fd[1], buf, attempt_to_write);
+                    if (nwritten < 0)
                       {
-                        if (exit_on_error)
-                          error (EXIT_FAILURE, errno,
-                                 _("write to %s subprocess failed"), progname);
-                        goto fail;
+                        if (errno == EAGAIN)
+                          {
+                            attempt_to_write = attempt_to_write / 2;
+                            if (attempt_to_write == 0)
+                              break;
+                          }
+                        else if (!IS_EAGAIN (errno))
+                          {
+                            if (exit_on_error)
+                              error (EXIT_FAILURE, errno,
+                                     _("write to %s subprocess failed"),
+                                     progname);
+                            goto fail;
+                          }
+                      }
+                    else
+                      {
+                        if (nwritten > 0)
+                          done_write ((void *) buf, nwritten, private_data);
+                        break;
                       }
                   }
-                else if (nwritten > 0)
-                  done_write ((void *) buf, nwritten, private_data);
               }
             else
               {