coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Unexpected behavior of 'tail --follow=name' on special file via syml


From: Pádraig Brady
Subject: Re: Unexpected behavior of 'tail --follow=name' on special file via symlink
Date: Wed, 1 Feb 2023 20:37:47 +0000
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Thunderbird/109.0

On 01/02/2023 14:46, Glenn Golden wrote:
Pádraig Brady <P@draigBrady.com> [2023-01-31 21:47:43 +0000]:
On 31/01/2023 19:48, Glenn Golden wrote:
Thanks, Pádraig.

With the above patch (applied manually to coreutils 9.1 sources) the
'illegal seek' no longer occurs, but it also doesn't follow the new file:
There is no output at all after tail announces that it is "following new file."

I did verify that the "new" instance of /dev/ttyMYDEV, when observed from
another independent process (via cat, less, more, tail, etc.) is indeed
sinking output from the device, as expected. But tail just isn't seeing it.

Also fiddled about with --sleep-interval=N (with several values of N) and
--retry as well, but no joy.

The output from `strace tail ...` would be useful I think to help diagnose.


Strace output attached, obtained via

     $ strace -tt --decode-fds=dev,path  \
           tail_p1 --follow=name --lines=+0 /dev/ttyPSLOG 2> strace1.out

where "tail_p1" is the patched 9.1 executable (your patch from the other day).

Note that there's an interesting bit of headscratch on line 199, just after
issuance of the "following new file" message. Looks like strace itself may
have overwritten its own buffer or something.

I ran strace several times, invoking it exactly as shown above, just to see
if that little feature was present each time, and it is.  I have no clue what
that is due to, or what strace output (if any) may have been lost there.

That was informative thanks.
What I think is happening is that to support --follow=name
tail(1) operates in non blocking mode so that it doesn't
block when reading a file, and has the opportunity to recheck.

Now it determines when a read() shouldn't block by
doing stat() and if size or mtime haven't changed,
then it doesn't perform the read. In fact for non regular files
it only goes on the mtime, which I guess is not changing for your device.

Note if you were just doing --follow=descriptor on a single file
tail(1) would operate in a simpler blocking manner
and would work fine with your device I expect
(not through the changing symlink of course).

I wonder could we try the read() anyway when operating on a
a single non regular file that has successfully been set in non blocking mode?
In that case we shouldn't block and read() would return 0 if no data.
I haven't thought about that much, but the diff below should do it.
At least it shows the part of the code involved,
which compares the various stat() members to determine to read or not.
Perhaps you could add debugging there (or strace -v -e fstat,newfstatat ...).
For example to see if st_size changes for you
(I don't think there is any other stat member we could key on).

cheers,
Pádraig

diff --git a/src/tail.c b/src/tail.c
index 2244509dd..309d93072 100644
--- a/src/tail.c
+++ b/src/tail.c
@@ -1243,7 +1243,8 @@ tail_forever (struct File_spec *f, size_t n_files, double 
sleep_interval)
                       recheck (&f[i], f[i].blocking);
                       f[i].n_unchanged_stats = 0;
                     }
-                  continue;
+                  if (S_ISREG (stats.st_mode) || 1 < n_files)
+                    continue;
                 }

               /* This file has changed.  Print out what we can, and




reply via email to

[Prev in Thread] Current Thread [Next in Thread]