I notice that split --filter spuriously returned with
status 141 just because the filter finished early.
This is a fairly good way to reproduce:

yes | head -n200K | split -b1G --filter='head -c1 >/dev/null'

I avoided this by not unblocking SIGPIPEs before
calling closeout(), which just lets any pending SIGPIPEs through.
I can't see why we would need to unblock them.

cheers,
Pádraig.
>From 4a497001757191a38a27dd8b8e28ecbc78869b57 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <[email protected]>
Date: Thu, 19 May 2011 23:23:23 +0100
Subject: [PATCH] split: return success even if a --filter exits

src/split.c (main): Don't unblock SIGPIPE before cleanup,
as then any pending signals will be sent and cause
the main split process to exit with a non zero status (141).
* test/split/filter: Add a test for this case.
---
 src/split.c        |    6 ++----
 tests/split/filter |    4 ++++
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/src/split.c b/src/split.c
index 05315e6..ccd91fd 100644
--- a/src/split.c
+++ b/src/split.c
@@ -1218,15 +1218,15 @@ main (int argc, char **argv)
 
   /* When filtering, closure of one pipe must not terminate the process,
      as there may still be other streams expecting input from us.  */
-  sigemptyset (&newblocked);
   if (filter_command)
     {
       struct sigaction act;
+      sigemptyset (&newblocked);
       sigaction (SIGPIPE, NULL, &act);
       if (act.sa_handler != SIG_IGN)
         sigaddset (&newblocked, SIGPIPE);
+      sigprocmask (SIG_BLOCK, &newblocked, &oldblocked);
     }
-  sigprocmask (SIG_BLOCK, &newblocked, &oldblocked);
 
   switch (split_type)
     {
@@ -1264,8 +1264,6 @@ main (int argc, char **argv)
       abort ();
     }
 
-  sigprocmask (SIG_SETMASK, &oldblocked, NULL);
-
   if (close (STDIN_FILENO) != 0)
     error (EXIT_FAILURE, errno, "%s", infile);
   closeout (NULL, output_desc, filter_pid, outfile);
diff --git a/tests/split/filter b/tests/split/filter
index 4c25c5f..0614841 100755
--- a/tests/split/filter
+++ b/tests/split/filter
@@ -43,4 +43,8 @@ done
 split -e -n 10 --filter='xz > $FILE.xz' /dev/null || fail=1
 stat x?? 2>/dev/null && fail=1
 
+# Ensure SIGPIPEs sent by the children don't propagate back
+# where they would result in a non zero exit from split.
+yes | head -n200K | split -b1G --filter='head -c1 >/dev/null' || fail=1
+
 Exit $fail
-- 
1.7.4

Reply via email to