X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fpipe-filter-ii.c;h=8951f2ed1213f02e47db8127b1ba610c53b1cc42;hb=533101a268dc5015a140ff4695d8eeb04fbe57b6;hp=9c95aae7a74ad37c1feb126f8cc628a088873718;hpb=441aa3044f43e5572f58c354f01e6bc070acd5c7;p=gnulib.git diff --git a/lib/pipe-filter-ii.c b/lib/pipe-filter-ii.c index 9c95aae7a..8951f2ed1 100644 --- a/lib/pipe-filter-ii.c +++ b/lib/pipe-filter-ii.c @@ -1,5 +1,5 @@ /* Filtering of data through a subprocess. - Copyright (C) 2001-2003, 2008-2009 Free Software Foundation, Inc. + Copyright (C) 2001-2003, 2008-2013 Free Software Foundation, Inc. Written by Bruno Haible , 2009. This program is free software: you can redistribute it and/or modify @@ -33,7 +33,7 @@ #endif #include "error.h" -#include "pipe.h" +#include "spawn-pipe.h" #include "wait-process.h" #include "gettext.h" @@ -155,7 +155,7 @@ pipe_filter_ii_execute (const char *progname, return -1; #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ - /* Native Woe32 API. */ + /* Native Windows API. */ /* Pipes have a non-blocking mode, see function SetNamedPipeHandleState and the article "Named Pipe Type, Read, and Wait Modes", but Microsoft's documentation discourages its use. So don't use it. @@ -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 sufficient + space is not available in the pipe. See POSIX:2008 + . + 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 {