On 17/10/2024 22:38, Bernhard Voelker wrote:
Hi *,

I noticed that 'tail --pid' does not work when the file to follow is a FIFO.
Shouldn't --pid behave the same regardless whether it's a pipe or not?

# Good case.
$ rm f; touch f  # tail to follow regular file.
$ sleep 5 & timeout 10 tail -f --pid=$! f; echo $?
[3] 1030528
[3]+  Done                    sleep 5
0

# Bad case.
$ rm f; mkfifo f  # tail to follow a FIFO file.
$ sleep 5 & timeout 10 tail -f --pid=$! f; echo $?
[3] 1030559
[3]+  Done                    sleep 5
124

Looking at strace output, one can see that kill() is only invoked once in the 
FIFO case.

FWIW: it doesn't make a difference whether one uses -f or -F, whether the
monitored file is written to by another process or stays empty, or whether one
tries with the  --sleep-interval option.

In my testing the initial open() of the fifo blocks,
before the -f loops are processed.
If the monitored file was written by another process,
this _does_ unblock things for me, and --pid is processed.

The attached patch avoids the blocking behavior with fifos,
and thus honors the --pid checking in parallel (and passes all tests).

However I've only thought about this for a couple of minutes,
so need to consider all the implications.

cheers,
Pádraig
From 863e1142f24a2fca3409682a070244eae1ef31bc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <p...@draigbrady.com>
Date: Fri, 18 Oct 2024 13:40:13 +0100
Subject: [PATCH] tail: honor --pid with fifos

* src/tail.c (tail_file): Open files with O_NONBLOCK
so we don't block with fifos.
(pipe_bytes): Igore EAGAIN read() errors.
(pipe_lines): Likewise.
Reported by Berhard Voelker.
---
 src/tail.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/tail.c b/src/tail.c
index 33acf9ab3..fd26d249b 100644
--- a/src/tail.c
+++ b/src/tail.c
@@ -697,7 +697,7 @@ pipe_lines (char const *pretty_filename, int fd, uintmax_t n_lines,
 
   free (tmp);
 
-  if (n_read < 0)
+  if (n_read < 0 && errno != EAGAIN)
     {
       error (0, errno, _("error reading %s"), quoteaf (pretty_filename));
       ok = false;
@@ -825,7 +825,7 @@ pipe_bytes (char const *pretty_filename, int fd, uintmax_t n_bytes,
 
   free (tmp);
 
-  if (n_read < 0)
+  if (n_read < 0 && errno != EAGAIN)
     {
       error (0, errno, _("error reading %s"), quoteaf (pretty_filename));
       ok = false;
@@ -2015,7 +2015,7 @@ tail_file (struct File_spec *f, uintmax_t n_units)
       xset_binary_mode (STDIN_FILENO, O_BINARY);
     }
   else
-    fd = open (f->name, O_RDONLY | O_BINARY);
+    fd = open (f->name, O_RDONLY | O_BINARY | O_NONBLOCK);
 
   f->tailable = !(reopen_inaccessible_files && fd == -1);
 
-- 
2.47.0

Reply via email to