From eeb933be12752eeac6fa31e4a096f967e4e49794 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A1draig=20Brady?= Date: Wed, 1 Feb 2023 20:41:31 +0000 Subject: [PATCH 2/2] tail: improve --follow=name with single non regular files * src/tail (tail_forever): Attempt to read() from non blocking single non regular file, which shouldn't block, but also read data even when the mtime doesn't change. * NEWS: Mention the improvement. * THANKS.in: Thanks for detailed testing. --- NEWS | 4 ++++ THANKS.in | 1 + src/tail.c | 14 ++++++++++++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 6cd9a6198..89413e94e 100644 --- a/NEWS +++ b/NEWS @@ -128,6 +128,10 @@ GNU coreutils NEWS -*- outline -*- when removing directories. For example EIO will be faithfully diagnosed, rather than being conflated with ENOTEMPTY. + tail --follow=name now works with single non regular files whose + mtime doesn't reflect new data being available. + Previously tail would not show any new data in this case. + * Noteworthy changes in release 9.1 (2022-04-15) [stable] diff --git a/THANKS.in b/THANKS.in index a3d179a55..8d903268e 100644 --- a/THANKS.in +++ b/THANKS.in @@ -230,6 +230,7 @@ Gerald Pfeifer gerald@pfeifer.com Gerhard Poul gpoul@gnu.org Germano Leichsenring germano@jedi.cs.kobe-u.ac.jp Glen Lenker glen.lenker@gmail.com +Glenn Golden gdg@zplane.com GOTO Masanori gotom@debian.or.jp Greg Louis glouis@dynamicro.on.ca Greg McGary gkm@gnu.org diff --git a/src/tail.c b/src/tail.c index 03061e8bf..e2e7f4690 100644 --- a/src/tail.c +++ b/src/tail.c @@ -1222,6 +1222,7 @@ tail_forever (struct File_spec *f, size_t n_files, double sleep_interval) f[i].blocking = blocking; } + bool read_unchanged = false; if (!f[i].blocking) { if (fstat (fd, &stats) != 0) @@ -1244,9 +1245,14 @@ tail_forever (struct File_spec *f, size_t n_files, double sleep_interval) recheck (&f[i], f[i].blocking); f[i].n_unchanged_stats = 0; } - continue; + if (fd != f[i].fd || S_ISREG (stats.st_mode) || 1 < n_files) + continue; + else + read_unchanged = true; } + assert (fd == f[i].fd); + /* This file has changed. Print out what we can, and then keep looping. */ @@ -1254,7 +1260,8 @@ tail_forever (struct File_spec *f, size_t n_files, double sleep_interval) f[i].mode = stats.st_mode; /* reset counter */ - f[i].n_unchanged_stats = 0; + if (! read_unchanged) + f[i].n_unchanged_stats = 0; /* XXX: This is only a heuristic, as the file may have also been truncated and written to if st_size >= size @@ -1289,6 +1296,9 @@ tail_forever (struct File_spec *f, size_t n_files, double sleep_interval) bytes_read = dump_remainder (false, name, fd, bytes_to_read); + if (read_unchanged && bytes_read) + f[i].n_unchanged_stats = 0; + any_input |= (bytes_read != 0); f[i].size += bytes_read; } -- 2.26.2