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