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;