The "problem" is that a FIFO without data hangs on open(2), until data
is available, the same goes for the initial read of the file.

We could work around this by adding the O_NONBLOCK flag to a separate
open(2) call, but I know that this flag is frowned upon. Since gnu tail
shows the same behaviour I'm not sure if it's worth doing.

Since I'm not claiming to know all the edge-cases of O_NONBLOCK you
could carry this diff locally at your own risk. Or maybe if other
developers feel strong about this and are braver than me when it comes
to O_NONBLOCK it might go somewhere.

martijn@

On Wed, 2022-06-08 at 22:09 -0400, Philippe Meunier wrote:
> Hi,
> 
> Try:
> 
> $ mkfifo fifo1 fifo2
> $ tail -f fifo1 fifo2
> 
> Then in another terminal:
> 
> $ while true; do /bin/echo aaaa > fifo1; done
> 
> and... nothing happens.  I would have expected tail(1) to start showing the
> content of fifo1 as soon as content became available but no, it just keeps
> waiting.
> 
> Then in another terminal:
> 
> $ while true; do /bin/echo bbbb > fifo2; done
> 
> and then tail(1) starts showing output as expected, alternating between
> fifo1 and fifo2.
> 
> The interesting part is that, once tail(1) has started producing output,
> you can interrupt and restart one or both of the "aaaa" and / or "bbbb"
> loops and tail(1) always does what you'd expect.  It seems that it's only
> at the very start that tail(1) doesn't produce any output until content is
> available in both fifos.
> 
> I tried various things like -n 0 and -c 0 but to no avail.
> 
> Another interesting thing to try:
> - start the "aaaa" loop
> - interrupt the "aaaa" loop
> - start the "bbbb" loop
> and tail(1) starts displaying output.
> 
> But if you try:
> - start the "bbbb" loop
> - interrupt the "bbbb" loop
> - start the "aaaa" loop
> then tail(1) still doesn't show any output, until you start the "bbbb" loop
> for a second time!
> 
> So at the very start, not only does tail(1) seem to expect content in both
> fifos before it start showing output, but it also seems to expect the
> content to appear in the specific order indicated on the tail(1) command
> line.
> 
> I assume this is a bug in tail(1)?
> 
> Cheers,
> 
> Philippe
> 
> 
Index: tail.c
===================================================================
RCS file: /cvs/src/usr.bin/tail/tail.c,v
retrieving revision 1.22
diff -u -p -r1.22 tail.c
--- tail.c      4 Jan 2019 15:04:28 -0000       1.22
+++ tail.c      9 Jun 2022 12:33:24 -0000
@@ -37,6 +37,7 @@
 
 #include <err.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -56,7 +57,7 @@ main(int argc, char *argv[])
        off_t off = 0;
        enum STYLE style;
        int ch;
-       int i;
+       int i, fd;
        char *p;
 
        if (pledge("stdio rpath", NULL) == -1)
@@ -154,8 +155,12 @@ main(int argc, char *argv[])
        if (argc) {
                for (i = 0; *argv; i++) {
                        tf[i].fname = *argv++;
-                       if ((tf[i].fp = fopen(tf[i].fname, "r")) == NULL ||
-                           fstat(fileno(tf[i].fp), &(tf[i].sb))) {
+                       /*
+                        * Use O_NONBLOCK to avoid hanging on FIFO.
+                        */
+                       fd = open(tf[i].fname, O_RDONLY | O_NONBLOCK);
+                       if (fd == -1 || (tf[i].fp = fdopen(fd, "r")) == NULL ||
+                           fstat(fd, &(tf[i].sb))) {
                                ierr(tf[i].fname);
                                i--;
                                continue;

Reply via email to