I'll finish this tomorrow.
To trigger the issue use:

split --filter="head -c1" -n r/1 /dev/zero
split --filter="head -c1" -n 1zero

cheers,
Pádraig
>From 1fb3191fb36a19c08edac1b65b042f04c6cbb024 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <[email protected]>
Date: Fri, 20 May 2011 01:26:41 +0100
Subject: [PATCH] split: exit when we can no longer write to a --filter

* src/split.c (bytes_split): Stop reading when we
can no longer write to a child process.
(lines_rr): Likewise.
(lines_bytes_split): TODO.
* test/split/filter: TODO.
---
 src/split.c |   15 +++++++++++++++
 1 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/src/split.c b/src/split.c
index 05315e6..0e13b5b 100644
--- a/src/split.c
+++ b/src/split.c
@@ -462,6 +462,12 @@ bytes_split (uintmax_t n_bytes, char *buf, size_t bufsize, uintmax_t max_files)
               cwrite (new_file_flag, bp_out, w);
               opened += new_file_flag;
               new_file_flag = !max_files || (opened < max_files);
+              if (!new_file_flag && ignorable (errno))
+                {
+                  /* If filter no longer accepting input, stop reading.  */
+                  n_read = 0;
+                  break;
+                }
               bp_out += w;
               to_read -= w;
               to_write = n_bytes;
@@ -805,6 +811,7 @@ static void
 lines_rr (uintmax_t k, uintmax_t n, char *buf, size_t bufsize)
 {
   bool wrapped = false;
+  bool wrote = false;
   bool file_limit;
   size_t i_file;
   of_t *files IF_LINT (= NULL);
@@ -891,6 +898,9 @@ lines_rr (uintmax_t k, uintmax_t n, char *buf, size_t bufsize)
               else if (fwrite (bp, to_write, 1, files[i_file].ofile) != 1
                        && ! ignorable (errno))
                 error (EXIT_FAILURE, errno, "%s", files[i_file].of_name);
+              if (! ignorable (errno))
+                wrote = true;
+
               if (file_limit)
                 {
                   if (fclose (files[i_file].ofile) != 0 && ! ignorable (errno))
@@ -901,6 +911,10 @@ lines_rr (uintmax_t k, uintmax_t n, char *buf, size_t bufsize)
               if (next && ++i_file == n)
                 {
                   wrapped = true;
+                  /* If no filters are accepting input, stop reading.  */
+                  if (! wrote)
+                    goto no_filters;
+                  wrote = false;
                   i_file = 0;
                 }
             }
@@ -909,6 +923,7 @@ lines_rr (uintmax_t k, uintmax_t n, char *buf, size_t bufsize)
         }
     }
 
+no_filters:
   /* Ensure all files created, so that any existing files are truncated,
      and to signal any waiting fifo consumers.
      Also, close any open file descriptors.
-- 
1.7.4

Reply via email to