You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
coreutils/SOURCES/coreutils-8.32-tail-use-pol...

182 lines
6.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

From c7a04cef4075da864a3468e63a5bb79334d8f556 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Sat, 26 Jun 2021 18:23:52 -0700
Subject: [PATCH] tail: use poll, not select
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This fixes an unlikely stack out-of-bounds write reported by
Stepan Broz via Kamil Dudka (Bug#49209).
* src/tail.c: Do not include <sys/select.h>.
[!_AIX]: Include poll.h.
(check_output_alive) [!_AIX]: Use poll instead of select.
(tail_forever_inotify): Likewise. Simplify logic, as there is no
need for a while (len <= evbuf_off) loop.
Upstream-commit: da0d448bca62c6305fc432f67e2c5ccc2da75346
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
src/tail.c | 100 +++++++++++++++++++++--------------------------------
1 file changed, 39 insertions(+), 61 deletions(-)
diff --git a/src/tail.c b/src/tail.c
index 1c88723..5b4f21a 100644
--- a/src/tail.c
+++ b/src/tail.c
@@ -28,12 +28,9 @@
#include <stdio.h>
#include <assert.h>
#include <getopt.h>
-#include <sys/select.h>
+#include <poll.h>
#include <sys/types.h>
#include <signal.h>
-#ifdef _AIX
-# include <poll.h>
-#endif
#include "system.h"
#include "argmatch.h"
@@ -351,27 +348,12 @@ check_output_alive (void)
if (! monitor_output)
return;
-#ifdef _AIX
- /* select on AIX was seen to give a readable event immediately. */
struct pollfd pfd;
pfd.fd = STDOUT_FILENO;
pfd.events = POLLERR;
if (poll (&pfd, 1, 0) >= 0 && (pfd.revents & POLLERR))
die_pipe ();
-#else
- struct timeval delay;
- delay.tv_sec = delay.tv_usec = 0;
-
- fd_set rfd;
- FD_ZERO (&rfd);
- FD_SET (STDOUT_FILENO, &rfd);
-
- /* 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)
- die_pipe ();
-#endif
}
static bool
@@ -1612,7 +1594,7 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files,
/* Wait for inotify events and handle them. Events on directories
ensure that watched files can be re-added when following by name.
This loop blocks on the 'safe_read' call until a new event is notified.
- But when --pid=P is specified, tail usually waits via the select. */
+ But when --pid=P is specified, tail usually waits via poll. */
while (1)
{
struct File_spec *fspec;
@@ -1629,54 +1611,51 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files,
return false;
}
- /* When watching a PID, ensure that a read from WD will not block
- indefinitely. */
- while (len <= evbuf_off)
+ if (len <= evbuf_off)
{
- struct timeval delay; /* how long to wait for file changes. */
+ /* Poll for inotify events. When watching a PID, ensure
+ that a read from WD will not block indefinitely.
+ If MONITOR_OUTPUT, also poll for a broken output pipe. */
- if (pid)
+ int file_change;
+ struct pollfd pfd[2];
+ do
{
- if (writer_is_dead)
- exit (EXIT_SUCCESS);
+ /* How many ms to wait for changes. -1 means wait forever. */
+ int delay = -1;
- writer_is_dead = (kill (pid, 0) != 0 && errno != EPERM);
-
- if (writer_is_dead)
- delay.tv_sec = delay.tv_usec = 0;
- else
+ if (pid)
{
- delay.tv_sec = (time_t) sleep_interval;
- delay.tv_usec = 1000000 * (sleep_interval - delay.tv_sec);
+ if (writer_is_dead)
+ exit (EXIT_SUCCESS);
+
+ writer_is_dead = (kill (pid, 0) != 0 && errno != EPERM);
+
+ if (writer_is_dead || sleep_interval <= 0)
+ delay = 0;
+ else if (sleep_interval < INT_MAX / 1000 - 1)
+ {
+ /* delay = ceil (sleep_interval * 1000), sans libm. */
+ double ddelay = sleep_interval * 1000;
+ delay = ddelay;
+ delay += delay < ddelay;
+ }
}
+
+ pfd[0].fd = wd;
+ pfd[0].events = POLLIN;
+ pfd[1].fd = STDOUT_FILENO;
+ pfd[1].events = pfd[1].revents = 0;
+ file_change = poll (pfd, monitor_output + 1, delay);
}
+ while (file_change == 0);
- fd_set rfd;
- FD_ZERO (&rfd);
- FD_SET (wd, &rfd);
- if (monitor_output)
- FD_SET (STDOUT_FILENO, &rfd);
-
- int file_change = select (MAX (wd, STDOUT_FILENO) + 1,
- &rfd, NULL, NULL, pid ? &delay: NULL);
-
- if (file_change == 0)
- continue;
- else if (file_change == -1)
- die (EXIT_FAILURE, errno,
- _("error waiting for inotify and output events"));
- else if (FD_ISSET (STDOUT_FILENO, &rfd))
- {
- /* readable event on STDOUT is equivalent to POLLERR,
- and implies an error on output like broken pipe. */
- die_pipe ();
- }
- else
- break;
- }
+ if (file_change < 0)
+ die (EXIT_FAILURE, errno,
+ _("error waiting for inotify and output events"));
+ if (pfd[1].revents)
+ die_pipe ();
- if (len <= evbuf_off)
- {
len = safe_read (wd, evbuf, evlen);
evbuf_off = 0;
@@ -2437,8 +2416,7 @@ main (int argc, char **argv)
if (forever && ignore_fifo_and_pipe (F, n_files))
{
/* If stdout is a fifo or pipe, then monitor it
- so that we exit if the reader goes away.
- Note select() on a regular file is always readable. */
+ so that we exit if the reader goes away. */
struct stat out_stat;
if (fstat (STDOUT_FILENO, &out_stat) < 0)
die (EXIT_FAILURE, errno, _("standard output"));
--
2.31.1