Subject: "tail -f - foo" does not terminate when stdin is closed and foo is ignored

From: Julian Büning <[email-masked]>
Date: Tue, 8 Nov 2016 17:39:18 +0100

We observed another behavior possibly related to bug #24495:

$ mkdir foo
$ echo "bar" | tail -f - foo &
[1] 16386
==> standard input <==
bar

==> foo <==
tail: error reading 'foo': Is a directory
tail: foo: cannot follow end of this type of file; giving up on this name
$ jobs
[1]+  Running                 echo "bar" | tail -f - foo &
$ readlink /proc/16386/fd/0
pipe:[162156]
$ lsof | grep 162156
tail      16386          user    0r     FIFO       0,10       0t0
162156 pipe

Only the reading end of the pipe is still open, thus tail should not be
able to read any more bytes from it.

expected behavior:

$ mkdir foo
$ echo "bar" | tail -f - foo &
[1] 16386
==> standard input <==
bar

==> foo <==
tail: error reading 'foo': Is a directory
tail: foo: cannot follow end of this type of file; giving up on this name
tail: no files remaining
[1]+  Done                    echo "bar" | tail -f - foo &

This would match the behavior of tail when called without a directory as
parameter:

$ echo "bar" | tail -f - &
[1] 8411
bar
[1]+  Done                    echo "bar" | tail -f -

We could reproduce this behavior with version 8.25 (package) and
8.25.91-23066 (compiled from source) on Fedora.

We need the directory (or some other untailable file) as second argument 
to reproduce this behavior as the -f option is ignored for any FIFO or 
pipe using ignore_fifo_and_pipe(), which prevents tail_forever() from 
being called in case only FIFOs or pipes are available. The 
aforementioned function sets .ignore to true for any FIFO or pipe.

In our test case, tail_forever() skips both the directory and stdin as
their .ignore entries are set to true. Before sleeping and starting the
next iteration of the loop (without making any attempt to read from
stdin), any_live_files() is called, which returns true for stdin:
  > if (0 <= f[i].fd)
  >    return true;

This behavior was found using Symbolic Execution techniques developed in
the course of the SYMBIOSYS research project at COMSYS, RWTH Aachen
University.

Regards,
Julian Büning