]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
tail: fix handling of broken pipes with SIGPIPE ignored
authorPádraig Brady <P@draigBrady.com>
Sun, 20 Jan 2019 08:13:15 +0000 (00:13 -0800)
committerPádraig Brady <P@draigBrady.com>
Sun, 20 Jan 2019 20:53:24 +0000 (12:53 -0800)
* init.cfg (trap_sigpipe_or_skip_): A new function refactored from...
* tests/misc/printf-surprise.sh: ...here.
* tests/misc/seq-epipe.sh. Likewise.
* src/tail.c (die_pipe): Ensure we exit upon sending SIGPIPE.
* tests/tail-2/pipe-f.sh: Ensure we exit even if SIGPIPE is ignored.
* NEWS: Mention the bug fix.

NEWS
init.cfg
src/tail.c
tests/misc/printf-surprise.sh
tests/misc/seq-epipe.sh
tests/tail-2/pipe-f.sh

diff --git a/NEWS b/NEWS
index ca296b09662c0b2e4acd9de98793aed2a5d00a2b..a6a02d8e7aebae2a55154cb976ea0295639f4c8d 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -27,6 +27,10 @@ GNU coreutils NEWS                                    -*- outline -*-
   'tail -f file | filter' no longer exits immediately on AIX.
   [bug introduced in coreutils-8.28]
 
+  'tail -f file | filter' no longer goes into an infinite loop
+  if filter exits and SIGPIPE is ignored.
+  [bug introduced in coreutils-8.28]
+
 ** Changes in behavior
 
   echo now always processes backslash escapes when the POSIXLY_CORRECT
index d99a0e3dd9ab8b89c6353fddfbbbbec18438c9d5..739ba33df42b42990edea9eb1b498a704acbf6aa 100644 (file)
--- a/init.cfg
+++ b/init.cfg
@@ -610,6 +610,12 @@ mkfifo_or_skip_()
   fi
 }
 
+trap_sigpipe_or_skip_()
+{
+  (trap '' PIPE && yes | :) 2>&1 | grep -qF 'Broken pipe' ||
+    skip_ 'trapping SIGPIPE is not supported'
+}
+
 # Disable the current test if the working directory seems to have
 # the setgid bit set.
 skip_if_setgid_()
index c63b61631718f4814dd99748c8ac950d2a558ed4..b8064853fe4228892432aed3316fbcb997e88139 100644 (file)
@@ -334,6 +334,14 @@ named file in a way that accommodates renaming, removal and creation.\n\
   exit (status);
 }
 
+/* Ensure exit, either with SIGPIPE or EXIT_FAILURE status.  */
+static void ATTRIBUTE_NORETURN
+die_pipe (void)
+{
+  raise (SIGPIPE);
+  exit (EXIT_FAILURE);
+}
+
 /* If the output has gone away, then terminate
    as we would if we had written to this output.  */
 static void
@@ -349,7 +357,7 @@ check_output_alive (void)
   pfd.events = POLLERR;
 
   if (poll (&pfd, 1, 0) >= 0 && (pfd.revents & POLLERR))
-    raise (SIGPIPE);
+    die_pipe ();
 #else
   struct timeval delay;
   delay.tv_sec = delay.tv_usec = 0;
@@ -361,7 +369,7 @@ check_output_alive (void)
   /* readable event on STDOUT is equivalent to POLLERR,
      and implies an error condition on output like broken pipe.  */
   if (select (STDOUT_FILENO + 1, &rfd, NULL, NULL, &delay) == 1)
-    raise (SIGPIPE);
+    die_pipe ();
 #endif
 }
 
@@ -1659,7 +1667,7 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files,
              {
                /* readable event on STDOUT is equivalent to POLLERR,
                   and implies an error on output like broken pipe.  */
-               raise (SIGPIPE);
+               die_pipe ();
              }
            else
              break;
index 18d48a0a72fe9f56c59986b0d94924df87c4f634..4190c949f12befde91ca540f968a8d4464a8d215 100755 (executable)
@@ -49,9 +49,7 @@ vm=$(get_min_ulimit_v_ env $prog %20f 0) \
 # triggering the printf(3) misbehavior -- which, btw, is required by ISO C99.
 
 mkfifo_or_skip_ fifo
-
-(trap '' PIPE && yes | :) 2>&1 | grep -qF 'Broken pipe' ||
-    skip_ 'trapping SIGPIPE is not supported'
+trap_sigpipe_or_skip_
 
 # Disable MALLOC_PERTURB_, to avoid triggering this bug
 # https://bugs.debian.org/481543#77
index be9457e945e70b86d9ba83860eb67aed6c4912f9..c2a6164a72e8e3d3a6a6c25dd575b7e4a408fb82 100755 (executable)
@@ -18,9 +18,7 @@
 
 . "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
 print_ver_ seq
-
-(trap '' PIPE && yes | :) 2>&1 | grep -qF 'Broken pipe' ||
-    skip_ 'trapping SIGPIPE is not supported'
+trap_sigpipe_or_skip_
 
 # upon EPIPE with signals ignored, 'seq' should exit with an error.
 timeout 10 sh -c \
index 4a5b444f364c1c7e894c6c4d9363f3322ac3cace..83f072ed51f47b50b31cb534bc3d157058c95ab2 100755 (executable)
@@ -18,6 +18,7 @@
 
 . "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
 print_ver_ tail
+trap_sigpipe_or_skip_
 
 # Speedup the non inotify case
 fastpoll='-s.1 --max-unchanged-stats=1'
@@ -36,11 +37,19 @@ echo bar | returns_ 1 \
 compare exp out || fail=1
 
 # This would wait indefinitely before v8.28 due to no EPIPE being
-# generated due to no data written after the first small amount
-(returns_ 124 timeout 10 tail -n2 -f $mode $fastpoll out && touch timed_out) |
- sed 2q > out2
-test -e timed_out && fail=1
-compare exp out2 || fail=1
+# generated due to no data written after the first small amount.
+# Also check tail exits if SIGPIPE is being ignored.
+# Note 'trap - SIGPIPE' is ineffective if the initiating shell
+# has ignored SIGPIPE, but that's not the normal case.
+for disposition in '' '-'; do
+  (trap "$disposition" PIPE;
+   returns_ 124 timeout 10 \
+    tail -n2 -f $mode $fastpoll out && touch timed_out) |
+  sed 2q > out2
+  test -e timed_out && fail=1
+  compare exp out2 || fail=1
+  rm -f timed_out
+done
 
 # This would wait indefinitely before v8.28 (until first write)
 (returns_ 1 timeout 10 tail -f $mode $fastpoll /dev/null >&-) || fail=1