a3bbf3
From 95f427178720d047316e95f44777cfdf2ecf2b46 Mon Sep 17 00:00:00 2001
a3bbf3
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <P@draigBrady.com>
a3bbf3
Date: Fri, 4 Jan 2019 09:29:13 -0800
a3bbf3
Subject: [PATCH 1/4] tail: don't exit immediately with filters on AIX
a3bbf3
a3bbf3
* src/tail.c: Fix the check_output_available check on AIX.
a3bbf3
Note we don't use poll for all systems as the overhead
a3bbf3
of adding the gnulib poll module wouldn't be worth it
a3bbf3
just for this single use.
a3bbf3
* tests/tail-2/pipe-f.sh: Fix the test which always passed
a3bbf3
due to only the exit code of sleep being checked.
a3bbf3
* NEWS: Mention the bug fix and rearrange alphabetically.
a3bbf3
Fixes http://bugs.gnu.org/33946
a3bbf3
a3bbf3
Upstream-commit: d5ab4cbe424e3e95140eec22ef828f50b2fb3067
a3bbf3
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
a3bbf3
---
a3bbf3
 src/tail.c             | 13 +++++++++++++
a3bbf3
 tests/tail-2/pipe-f.sh |  5 ++++-
a3bbf3
 2 files changed, 17 insertions(+), 1 deletion(-)
a3bbf3
a3bbf3
diff --git a/src/tail.c b/src/tail.c
a3bbf3
index ac001d7..d63aacc 100644
a3bbf3
--- a/src/tail.c
a3bbf3
+++ b/src/tail.c
a3bbf3
@@ -30,6 +30,9 @@
a3bbf3
 #include <getopt.h>
a3bbf3
 #include <sys/types.h>
a3bbf3
 #include <signal.h>
a3bbf3
+#ifdef _AIX
a3bbf3
+# include <poll.h>
a3bbf3
+#endif
a3bbf3
 
a3bbf3
 #include "system.h"
a3bbf3
 #include "argmatch.h"
a3bbf3
@@ -335,6 +338,16 @@ named file in a way that accommodates renaming, removal and creation.\n\
a3bbf3
 static void
a3bbf3
 check_output_alive (void)
a3bbf3
 {
a3bbf3
+#ifdef _AIX
a3bbf3
+  /* select on AIX was seen to give a readable event immediately.  */
a3bbf3
+  struct pollfd pfd;
a3bbf3
+  pfd.fd = STDOUT_FILENO;
a3bbf3
+  pfd.events = POLLERR;
a3bbf3
+
a3bbf3
+  if (poll (&pfd, 1, 0) >= 0 && (pfd.revents & POLLERR))
a3bbf3
+    raise (SIGPIPE);
a3bbf3
+#endif
a3bbf3
+
a3bbf3
   if (! monitor_output)
a3bbf3
     return;
a3bbf3
 
a3bbf3
diff --git a/tests/tail-2/pipe-f.sh b/tests/tail-2/pipe-f.sh
a3bbf3
index 76b0d90..1126c93 100755
a3bbf3
--- a/tests/tail-2/pipe-f.sh
a3bbf3
+++ b/tests/tail-2/pipe-f.sh
a3bbf3
@@ -37,7 +37,10 @@ compare exp out || fail=1
a3bbf3
 
a3bbf3
 # This would wait indefinitely before v8.28 due to no EPIPE being
a3bbf3
 # generated due to no data written after the first small amount
a3bbf3
-timeout 10 tail -f $mode $fastpoll out | sleep .1 || fail=1
a3bbf3
+(returns_ 124 timeout 10 tail -n2 -f $mode $fastpoll out && touch timed_out) |
a3bbf3
+ sed 2q > out2
a3bbf3
+test -e timed_out && fail=1
a3bbf3
+compare exp out2 || fail=1
a3bbf3
 
a3bbf3
 # This would wait indefinitely before v8.28 (until first write)
a3bbf3
 (returns_ 1 timeout 10 tail -f $mode $fastpoll /dev/null >&-) || fail=1
a3bbf3
-- 
a3bbf3
2.31.1
a3bbf3
a3bbf3
a3bbf3
From 125bb79d3e9f414533b1c29237ee3f647053d0d6 Mon Sep 17 00:00:00 2001
a3bbf3
From: Ayappan <ayappap2@in.ibm.com>
a3bbf3
Date: Sun, 20 Jan 2019 00:17:33 -0800
a3bbf3
Subject: [PATCH 2/4] tail: fix recent ineffective AIX change
a3bbf3
a3bbf3
* src/tail.c: Fix commit v8.30-40-gd5ab4cb which was ineffective.
a3bbf3
Fixes http://bugs.gnu.org/33946
a3bbf3
a3bbf3
Upstream-commit: 17983b2cb3bccbb4fa69691178caddd99269bda9
a3bbf3
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
a3bbf3
---
a3bbf3
 src/tail.c | 10 +++++-----
a3bbf3
 1 file changed, 5 insertions(+), 5 deletions(-)
a3bbf3
a3bbf3
diff --git a/src/tail.c b/src/tail.c
a3bbf3
index d63aacc..9ed6d48 100644
a3bbf3
--- a/src/tail.c
a3bbf3
+++ b/src/tail.c
a3bbf3
@@ -338,6 +338,9 @@ named file in a way that accommodates renaming, removal and creation.\n\
a3bbf3
 static void
a3bbf3
 check_output_alive (void)
a3bbf3
 {
a3bbf3
+  if (! monitor_output)
a3bbf3
+    return;
a3bbf3
+
a3bbf3
 #ifdef _AIX
a3bbf3
   /* select on AIX was seen to give a readable event immediately.  */
a3bbf3
   struct pollfd pfd;
a3bbf3
@@ -346,11 +349,7 @@ check_output_alive (void)
a3bbf3
 
a3bbf3
   if (poll (&pfd, 1, 0) >= 0 && (pfd.revents & POLLERR))
a3bbf3
     raise (SIGPIPE);
a3bbf3
-#endif
a3bbf3
-
a3bbf3
-  if (! monitor_output)
a3bbf3
-    return;
a3bbf3
-
a3bbf3
+#else
a3bbf3
   struct timeval delay;
a3bbf3
   delay.tv_sec = delay.tv_usec = 0;
a3bbf3
 
a3bbf3
@@ -362,6 +361,7 @@ check_output_alive (void)
a3bbf3
      and implies an error condition on output like broken pipe.  */
a3bbf3
   if (select (STDOUT_FILENO + 1, &rfd, NULL, NULL, &delay) == 1)
a3bbf3
     raise (SIGPIPE);
a3bbf3
+#endif
a3bbf3
 }
a3bbf3
 
a3bbf3
 static bool
a3bbf3
-- 
a3bbf3
2.31.1
a3bbf3
a3bbf3
a3bbf3
From 7741989c3e633aa44f01d8f91332cb65a9280ba3 Mon Sep 17 00:00:00 2001
a3bbf3
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <P@draigBrady.com>
a3bbf3
Date: Sun, 20 Jan 2019 00:13:15 -0800
a3bbf3
Subject: [PATCH 3/4] tail: fix handling of broken pipes with SIGPIPE ignored
a3bbf3
a3bbf3
* init.cfg (trap_sigpipe_or_skip_): A new function refactored from...
a3bbf3
* tests/misc/printf-surprise.sh: ...here.
a3bbf3
* tests/misc/seq-epipe.sh. Likewise.
a3bbf3
* src/tail.c (die_pipe): Ensure we exit upon sending SIGPIPE.
a3bbf3
* tests/tail-2/pipe-f.sh: Ensure we exit even if SIGPIPE is ignored.
a3bbf3
* NEWS: Mention the bug fix.
a3bbf3
a3bbf3
Upstream-commit: fa50623394f491b975dbd7ad73193519dd721771
a3bbf3
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
a3bbf3
---
a3bbf3
 init.cfg                      |  6 ++++++
a3bbf3
 src/tail.c                    | 14 +++++++++++---
a3bbf3
 tests/misc/printf-surprise.sh |  4 +---
a3bbf3
 tests/misc/seq-epipe.sh       |  4 +---
a3bbf3
 tests/tail-2/pipe-f.sh        | 19 ++++++++++++++-----
a3bbf3
 5 files changed, 33 insertions(+), 14 deletions(-)
a3bbf3
a3bbf3
diff --git a/init.cfg b/init.cfg
a3bbf3
index b6c81ab..985c8d3 100644
a3bbf3
--- a/init.cfg
a3bbf3
+++ b/init.cfg
a3bbf3
@@ -613,6 +613,12 @@ mkfifo_or_skip_()
a3bbf3
   fi
a3bbf3
 }
a3bbf3
 
a3bbf3
+trap_sigpipe_or_skip_()
a3bbf3
+{
a3bbf3
+  (trap '' PIPE && yes | :) 2>&1 | grep -qF 'Broken pipe' ||
a3bbf3
+    skip_ 'trapping SIGPIPE is not supported'
a3bbf3
+}
a3bbf3
+
a3bbf3
 # Disable the current test if the working directory seems to have
a3bbf3
 # the setgid bit set.
a3bbf3
 skip_if_setgid_()
a3bbf3
diff --git a/src/tail.c b/src/tail.c
a3bbf3
index 9ed6d48..16e0d73 100644
a3bbf3
--- a/src/tail.c
a3bbf3
+++ b/src/tail.c
a3bbf3
@@ -333,6 +333,14 @@ named file in a way that accommodates renaming, removal and creation.\n\
a3bbf3
   exit (status);
a3bbf3
 }
a3bbf3
 
a3bbf3
+/* Ensure exit, either with SIGPIPE or EXIT_FAILURE status.  */
a3bbf3
+static void ATTRIBUTE_NORETURN
a3bbf3
+die_pipe (void)
a3bbf3
+{
a3bbf3
+  raise (SIGPIPE);
a3bbf3
+  exit (EXIT_FAILURE);
a3bbf3
+}
a3bbf3
+
a3bbf3
 /* If the output has gone away, then terminate
a3bbf3
    as we would if we had written to this output.  */
a3bbf3
 static void
a3bbf3
@@ -348,7 +356,7 @@ check_output_alive (void)
a3bbf3
   pfd.events = POLLERR;
a3bbf3
 
a3bbf3
   if (poll (&pfd, 1, 0) >= 0 && (pfd.revents & POLLERR))
a3bbf3
-    raise (SIGPIPE);
a3bbf3
+    die_pipe ();
a3bbf3
 #else
a3bbf3
   struct timeval delay;
a3bbf3
   delay.tv_sec = delay.tv_usec = 0;
a3bbf3
@@ -360,7 +368,7 @@ check_output_alive (void)
a3bbf3
   /* readable event on STDOUT is equivalent to POLLERR,
a3bbf3
      and implies an error condition on output like broken pipe.  */
a3bbf3
   if (select (STDOUT_FILENO + 1, &rfd, NULL, NULL, &delay) == 1)
a3bbf3
-    raise (SIGPIPE);
a3bbf3
+    die_pipe ();
a3bbf3
 #endif
a3bbf3
 }
a3bbf3
 
a3bbf3
@@ -1658,7 +1666,7 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files,
a3bbf3
              {
a3bbf3
                /* readable event on STDOUT is equivalent to POLLERR,
a3bbf3
                   and implies an error on output like broken pipe.  */
a3bbf3
-               raise (SIGPIPE);
a3bbf3
+               die_pipe ();
a3bbf3
              }
a3bbf3
            else
a3bbf3
              break;
a3bbf3
diff --git a/tests/misc/printf-surprise.sh b/tests/misc/printf-surprise.sh
a3bbf3
index fd88133..acac0b1 100755
a3bbf3
--- a/tests/misc/printf-surprise.sh
a3bbf3
+++ b/tests/misc/printf-surprise.sh
a3bbf3
@@ -49,9 +49,7 @@ vm=$(get_min_ulimit_v_ env $prog %20f 0) \
a3bbf3
 # triggering the printf(3) misbehavior -- which, btw, is required by ISO C99.
a3bbf3
 
a3bbf3
 mkfifo_or_skip_ fifo
a3bbf3
-
a3bbf3
-(trap '' PIPE && yes | :) 2>&1 | grep -qF 'Broken pipe' ||
a3bbf3
-    skip_ 'trapping SIGPIPE is not supported'
a3bbf3
+trap_sigpipe_or_skip_
a3bbf3
 
a3bbf3
 # Disable MALLOC_PERTURB_, to avoid triggering this bug
a3bbf3
 # https://bugs.debian.org/481543#77
a3bbf3
diff --git a/tests/misc/seq-epipe.sh b/tests/misc/seq-epipe.sh
a3bbf3
index 3e89158..127d61c 100755
a3bbf3
--- a/tests/misc/seq-epipe.sh
a3bbf3
+++ b/tests/misc/seq-epipe.sh
a3bbf3
@@ -18,9 +18,7 @@
a3bbf3
 
a3bbf3
 . "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
a3bbf3
 print_ver_ seq
a3bbf3
-
a3bbf3
-(trap '' PIPE && yes | :) 2>&1 | grep -qF 'Broken pipe' ||
a3bbf3
-    skip_ 'trapping SIGPIPE is not supported'
a3bbf3
+trap_sigpipe_or_skip_
a3bbf3
 
a3bbf3
 # upon EPIPE with signals ignored, 'seq' should exit with an error.
a3bbf3
 timeout 10 sh -c \
a3bbf3
diff --git a/tests/tail-2/pipe-f.sh b/tests/tail-2/pipe-f.sh
a3bbf3
index 1126c93..f734a61 100755
a3bbf3
--- a/tests/tail-2/pipe-f.sh
a3bbf3
+++ b/tests/tail-2/pipe-f.sh
a3bbf3
@@ -18,6 +18,7 @@
a3bbf3
 
a3bbf3
 . "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
a3bbf3
 print_ver_ tail
a3bbf3
+trap_sigpipe_or_skip_
a3bbf3
 
a3bbf3
 # Speedup the non inotify case
a3bbf3
 fastpoll='-s.1 --max-unchanged-stats=1'
a3bbf3
@@ -36,11 +37,19 @@ echo bar | returns_ 1 \
a3bbf3
 compare exp out || fail=1
a3bbf3
 
a3bbf3
 # This would wait indefinitely before v8.28 due to no EPIPE being
a3bbf3
-# generated due to no data written after the first small amount
a3bbf3
-(returns_ 124 timeout 10 tail -n2 -f $mode $fastpoll out && touch timed_out) |
a3bbf3
- sed 2q > out2
a3bbf3
-test -e timed_out && fail=1
a3bbf3
-compare exp out2 || fail=1
a3bbf3
+# generated due to no data written after the first small amount.
a3bbf3
+# Also check tail exits if SIGPIPE is being ignored.
a3bbf3
+# Note 'trap - SIGPIPE' is ineffective if the initiating shell
a3bbf3
+# has ignored SIGPIPE, but that's not the normal case.
a3bbf3
+for disposition in '' '-'; do
a3bbf3
+  (trap "$disposition" PIPE;
a3bbf3
+   returns_ 124 timeout 10 \
a3bbf3
+    tail -n2 -f $mode $fastpoll out && touch timed_out) |
a3bbf3
+  sed 2q > out2
a3bbf3
+  test -e timed_out && fail=1
a3bbf3
+  compare exp out2 || fail=1
a3bbf3
+  rm -f timed_out
a3bbf3
+done
a3bbf3
 
a3bbf3
 # This would wait indefinitely before v8.28 (until first write)
a3bbf3
 (returns_ 1 timeout 10 tail -f $mode $fastpoll /dev/null >&-) || fail=1
a3bbf3
-- 
a3bbf3
2.31.1
a3bbf3
a3bbf3
a3bbf3
From 0f5760466d167e955d28a1250ffd0af347d48dc9 Mon Sep 17 00:00:00 2001
a3bbf3
From: Paul Eggert <eggert@cs.ucla.edu>
a3bbf3
Date: Sat, 26 Jun 2021 18:23:52 -0700
a3bbf3
Subject: [PATCH 4/4] tail: use poll, not select
a3bbf3
MIME-Version: 1.0
a3bbf3
Content-Type: text/plain; charset=UTF-8
a3bbf3
Content-Transfer-Encoding: 8bit
a3bbf3
a3bbf3
This fixes an unlikely stack out-of-bounds write reported by
a3bbf3
Stepan Broz via Kamil Dudka (Bug#49209).
a3bbf3
* src/tail.c: Do not include <sys/select.h>.
a3bbf3
[!_AIX]: Include poll.h.
a3bbf3
(check_output_alive) [!_AIX]: Use poll instead of select.
a3bbf3
(tail_forever_inotify): Likewise.  Simplify logic, as there is no
a3bbf3
need for a ‘while (len <= evbuf_off)’ loop.
a3bbf3
a3bbf3
Upstream-commit: da0d448bca62c6305fc432f67e2c5ccc2da75346
a3bbf3
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
a3bbf3
---
a3bbf3
 src/tail.c | 101 +++++++++++++++++++++--------------------------------
a3bbf3
 1 file changed, 39 insertions(+), 62 deletions(-)
a3bbf3
a3bbf3
diff --git a/src/tail.c b/src/tail.c
a3bbf3
index 16e0d73..d77c660 100644
a3bbf3
--- a/src/tail.c
a3bbf3
+++ b/src/tail.c
a3bbf3
@@ -29,10 +29,8 @@
a3bbf3
 #include <assert.h>
a3bbf3
 #include <getopt.h>
a3bbf3
 #include <sys/types.h>
a3bbf3
+#include <poll.h>
a3bbf3
 #include <signal.h>
a3bbf3
-#ifdef _AIX
a3bbf3
-# include <poll.h>
a3bbf3
-#endif
a3bbf3
 
a3bbf3
 #include "system.h"
a3bbf3
 #include "argmatch.h"
a3bbf3
@@ -55,8 +53,6 @@
a3bbf3
 #if HAVE_INOTIFY
a3bbf3
 # include "hash.h"
a3bbf3
 # include <sys/inotify.h>
a3bbf3
-/* 'select' is used by tail_forever_inotify.  */
a3bbf3
-# include <sys/select.h>
a3bbf3
 
a3bbf3
 /* inotify needs to know if a file is local.  */
a3bbf3
 # include "fs.h"
a3bbf3
@@ -349,27 +345,12 @@ check_output_alive (void)
a3bbf3
   if (! monitor_output)
a3bbf3
     return;
a3bbf3
 
a3bbf3
-#ifdef _AIX
a3bbf3
-  /* select on AIX was seen to give a readable event immediately.  */
a3bbf3
   struct pollfd pfd;
a3bbf3
   pfd.fd = STDOUT_FILENO;
a3bbf3
   pfd.events = POLLERR;
a3bbf3
 
a3bbf3
   if (poll (&pfd, 1, 0) >= 0 && (pfd.revents & POLLERR))
a3bbf3
     die_pipe ();
a3bbf3
-#else
a3bbf3
-  struct timeval delay;
a3bbf3
-  delay.tv_sec = delay.tv_usec = 0;
a3bbf3
-
a3bbf3
-  fd_set rfd;
a3bbf3
-  FD_ZERO (&rfd;;
a3bbf3
-  FD_SET (STDOUT_FILENO, &rfd;;
a3bbf3
-
a3bbf3
-  /* readable event on STDOUT is equivalent to POLLERR,
a3bbf3
-     and implies an error condition on output like broken pipe.  */
a3bbf3
-  if (select (STDOUT_FILENO + 1, &rfd, NULL, NULL, &delay) == 1)
a3bbf3
-    die_pipe ();
a3bbf3
-#endif
a3bbf3
 }
a3bbf3
 
a3bbf3
 static bool
a3bbf3
@@ -1609,7 +1590,7 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files,
a3bbf3
   /* Wait for inotify events and handle them.  Events on directories
a3bbf3
      ensure that watched files can be re-added when following by name.
a3bbf3
      This loop blocks on the 'safe_read' call until a new event is notified.
a3bbf3
-     But when --pid=P is specified, tail usually waits via the select.  */
a3bbf3
+     But when --pid=P is specified, tail usually waits via poll.  */
a3bbf3
   while (1)
a3bbf3
     {
a3bbf3
       struct File_spec *fspec;
a3bbf3
@@ -1626,54 +1607,51 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files,
a3bbf3
           return false;
a3bbf3
         }
a3bbf3
 
a3bbf3
-      /* When watching a PID, ensure that a read from WD will not block
a3bbf3
-         indefinitely.  */
a3bbf3
-      while (len <= evbuf_off)
a3bbf3
+      if (len <= evbuf_off)
a3bbf3
         {
a3bbf3
-          struct timeval delay; /* how long to wait for file changes.  */
a3bbf3
+          /* Poll for inotify events.  When watching a PID, ensure
a3bbf3
+             that a read from WD will not block indefinitely.
a3bbf3
+             If MONITOR_OUTPUT, also poll for a broken output pipe.  */
a3bbf3
 
a3bbf3
-          if (pid)
a3bbf3
+          int file_change;
a3bbf3
+          struct pollfd pfd[2];
a3bbf3
+          do
a3bbf3
             {
a3bbf3
-              if (writer_is_dead)
a3bbf3
-                exit (EXIT_SUCCESS);
a3bbf3
+              /* How many ms to wait for changes.  -1 means wait forever.  */
a3bbf3
+              int delay = -1;
a3bbf3
 
a3bbf3
-              writer_is_dead = (kill (pid, 0) != 0 && errno != EPERM);
a3bbf3
-
a3bbf3
-              if (writer_is_dead)
a3bbf3
-                delay.tv_sec = delay.tv_usec = 0;
a3bbf3
-              else
a3bbf3
+              if (pid)
a3bbf3
                 {
a3bbf3
-                  delay.tv_sec = (time_t) sleep_interval;
a3bbf3
-                  delay.tv_usec = 1000000 * (sleep_interval - delay.tv_sec);
a3bbf3
+                  if (writer_is_dead)
a3bbf3
+                    exit (EXIT_SUCCESS);
a3bbf3
+
a3bbf3
+                  writer_is_dead = (kill (pid, 0) != 0 && errno != EPERM);
a3bbf3
+
a3bbf3
+                  if (writer_is_dead || sleep_interval <= 0)
a3bbf3
+                    delay = 0;
a3bbf3
+                  else if (sleep_interval < INT_MAX / 1000 - 1)
a3bbf3
+                    {
a3bbf3
+                      /* delay = ceil (sleep_interval * 1000), sans libm.  */
a3bbf3
+                      double ddelay = sleep_interval * 1000;
a3bbf3
+                      delay = ddelay;
a3bbf3
+                      delay += delay < ddelay;
a3bbf3
+                    }
a3bbf3
                 }
a3bbf3
+
a3bbf3
+              pfd[0].fd = wd;
a3bbf3
+              pfd[0].events = POLLIN;
a3bbf3
+              pfd[1].fd = STDOUT_FILENO;
a3bbf3
+              pfd[1].events = pfd[1].revents = 0;
a3bbf3
+              file_change = poll (pfd, monitor_output + 1, delay);
a3bbf3
             }
a3bbf3
+          while (file_change == 0);
a3bbf3
 
a3bbf3
-           fd_set rfd;
a3bbf3
-           FD_ZERO (&rfd;;
a3bbf3
-           FD_SET (wd, &rfd;;
a3bbf3
-           if (monitor_output)
a3bbf3
-             FD_SET (STDOUT_FILENO, &rfd;;
a3bbf3
-
a3bbf3
-           int file_change = select (MAX (wd, STDOUT_FILENO) + 1,
a3bbf3
-                                     &rfd, NULL, NULL, pid ? &delay: NULL);
a3bbf3
-
a3bbf3
-           if (file_change == 0)
a3bbf3
-             continue;
a3bbf3
-           else if (file_change == -1)
a3bbf3
-             die (EXIT_FAILURE, errno,
a3bbf3
-                  _("error waiting for inotify and output events"));
a3bbf3
-           else if (FD_ISSET (STDOUT_FILENO, &rfd))
a3bbf3
-             {
a3bbf3
-               /* readable event on STDOUT is equivalent to POLLERR,
a3bbf3
-                  and implies an error on output like broken pipe.  */
a3bbf3
-               die_pipe ();
a3bbf3
-             }
a3bbf3
-           else
a3bbf3
-             break;
a3bbf3
-        }
a3bbf3
+          if (file_change < 0)
a3bbf3
+            die (EXIT_FAILURE, errno,
a3bbf3
+                 _("error waiting for inotify and output events"));
a3bbf3
+          if (pfd[1].revents)
a3bbf3
+            die_pipe ();
a3bbf3
 
a3bbf3
-      if (len <= evbuf_off)
a3bbf3
-        {
a3bbf3
           len = safe_read (wd, evbuf, evlen);
a3bbf3
           evbuf_off = 0;
a3bbf3
 
a3bbf3
@@ -2434,8 +2412,7 @@ main (int argc, char **argv)
a3bbf3
   if (forever && ignore_fifo_and_pipe (F, n_files))
a3bbf3
     {
a3bbf3
       /* If stdout is a fifo or pipe, then monitor it
a3bbf3
-         so that we exit if the reader goes away.
a3bbf3
-         Note select() on a regular file is always readable.  */
a3bbf3
+         so that we exit if the reader goes away.  */
a3bbf3
       struct stat out_stat;
a3bbf3
       if (fstat (STDOUT_FILENO, &out_stat) < 0)
a3bbf3
         die (EXIT_FAILURE, errno, _("standard output"));
a3bbf3
-- 
a3bbf3
2.31.1
a3bbf3