# HG changeset patch # User Bruno Haible # Date 1307294125 -7200 # Node ID d52404af032150f5a5b144b4288a9b2ced7c703d # Parent b8de6a14a6d5eea79fa51acd250d53e05463ca88 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. diff --git a/ChangeLog b/ChangeLog --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-06-05 Bruno Haible + + 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 localename: Fix link dependencies. diff --git a/lib/pipe-filter-ii.c b/lib/pipe-filter-ii.c --- a/lib/pipe-filter-ii.c +++ b/lib/pipe-filter-ii.c @@ -347,21 +347,42 @@ 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 + . + 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 {