Subject: bug#27368: Minor concern: Confusing tail warning

From: Pádraig Brady <[email-masked]>
Date: Thu, 15 Jun 2017 02:40:46 -0700

On 14/06/17 16:03, Charlie Hagedorn wrote:
> Hi!
> 
> Thank you for maintaining such useful and reliable tools.
> 
> Today I came across an unexpected warning in tail. The warning is intended
> to handle this case:
> 
> [:~]$ tail -f
> tail: warning: following standard input indefinitely is ineffective
> 
> which is both important and fun.
> 
> Today, however, I was surprised to see it appear in this context:
> 
> [:~]$ tail -f < /dev/ttyUSB0  > data.dat
> tail: warning: following standard input indefinitely is ineffective
> 
> The warning was confusing and perhaps inappropriate, as this call actually
> *does* something, and is very effective at doing what I want; streaming the
> port's output into data.dat.

Right. The above command will go into non inotify blocking mode
and will thus work as you expect.  Note tail will not output
anything until the first time read() returns nothing.
The following patch should suppress the warning if we would be using this mode.

diff --git a/src/tail.c b/src/tail.c
index 3918373..2f9b981 100644
--- a/src/tail.c
+++ b/src/tail.c
@@ -2365,12 +2365,22 @@ main (int argc, char **argv)
     if (found_hyphen && follow_mode == Follow_name)
       die (EXIT_FAILURE, 0, _("cannot follow %s by name"), quoteaf ("-"));

-    /* When following forever, warn if any file is '-'.
+    /* When following forever, and not using simple blocking, warn if
+       any file is '-' as the stats() used to check for input are ineffective.
        This is only a warning, since tail's output (before a failing seek,
        and that from any non-stdin files) might still be useful.  */
-    if (forever && found_hyphen && isatty (STDIN_FILENO))
-      error (0, 0, _("warning: following standard input"
-                     " indefinitely is ineffective"));
+    if (forever && found_hyphen)
+      {
+        struct stat in_stat;
+        bool blocking_stdin;
+        blocking_stdin = (pid == 0 && follow_mode == Follow_descriptor
+                          && n_files == 1 && ! fstat (STDIN_FILENO, &in_stat)
+                          && ! S_ISREG (in_stat.st_mode));
+
+        if (! blocking_stdin && isatty (STDIN_FILENO))
+          error (0, 0, _("warning: following standard input"
+                         " indefinitely is ineffective"));
+      }
   }

> (Importantly, for reasons I don't yet understand, tail -f /dev/ttyUSB0 >
> data.dat does not reliably tail the port; it redirects only one line of
> output instead of a continuous stream).

That looks like another case where we should be disabling inotify.
I.E. you can see this waits forever for inotify events if you hit ctrl-d a few times:

  strace tail -f /dev/tty

Ah yes that was discussed at http://bugs.gnu.org/21265
I suppose we should improve things here with a couple of patches.

1. Disable inotify if any non regular files (except fifo/pipe)
(the kernel should really disallow this, but best handle I think)

2. Generalise the warning in the above patch to be:
if (n_files > 1 && any_device_or_tty)
  printf ("warning: following a stdin/device in combination with other inputs is ineffective")

cheers,
Pádraig