mirror of
https://git.savannah.gnu.org/git/coreutils.git
synced 2025-09-10 07:59:52 +02:00
tail: ensure --follow=name unfollows renamed files
Require --retry to continue to track files upon rename. We already unfollowed a file if it was renamed to another file system (unlinked), so this makes the behavior consistent if renaming to a file in the same file system. I.e. --follow=name without --retry, means unfollow if the name is unlinked or moved, so this change ensures that behavior for all rename cases. Related commits: v8.0-121-g3b997a9bc, v8.23-161-gd313a0b24 * src/tail.c (tail_forever_notify): Remove watch for a renamed file if --retry is not specified. * tests/tail/F-vs-rename.sh: Related test cleanup. * tests/tail/follow-name.sh: Add a test case. * NEWS: Mention the bug fix. Fixes https://bugs.gnu.org/74653
This commit is contained in:
4
NEWS
4
NEWS
@@ -28,6 +28,10 @@ GNU coreutils NEWS -*- outline -*-
|
||||
'shuf' generates more-random output when the output is small.
|
||||
[bug introduced in coreutils-8.6]
|
||||
|
||||
`tail --follow=name` no longer waits indefinitely for watched
|
||||
file names that are moved elsewhere within the same file system.
|
||||
[bug introduced in coreutils-8.24]
|
||||
|
||||
'tail -c 4096 /dev/zero' no longer loops forever.
|
||||
[This bug was present in "the beginning".]
|
||||
|
||||
|
||||
@@ -1812,10 +1812,11 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files,
|
||||
if (ev->mask & (IN_ATTRIB | IN_DELETE | IN_DELETE_SELF | IN_MOVE_SELF))
|
||||
{
|
||||
/* Note for IN_MOVE_SELF (the file we're watching has
|
||||
been clobbered via a rename) we leave the watch
|
||||
been clobbered via a rename) without --retry we leave the watch
|
||||
in place since it may still be part of the set
|
||||
of watched names. */
|
||||
if (ev->mask & IN_DELETE_SELF)
|
||||
if (ev->mask & IN_DELETE_SELF
|
||||
|| (!reopen_inaccessible_files && (ev->mask & IN_MOVE_SELF)))
|
||||
{
|
||||
inotify_rm_watch (wd, fspec->wd);
|
||||
hash_remove (wd_to_name, fspec);
|
||||
|
||||
@@ -63,26 +63,26 @@ for mode in '' '---disable-inotify'; do
|
||||
{ cat out; fail=1; }
|
||||
# Wait up to 12.7s for "x" to be displayed:
|
||||
file='b' data='x' retry_delay_ check_tail_output .1 7 ||
|
||||
{ echo "$0: b: unexpected delay?"; cat out; fail=1; }
|
||||
{ echo "$0: b: unexpected delay 1?"; cat out; fail=1; }
|
||||
|
||||
echo x2 > a
|
||||
# Wait up to 12.7s for this to appear in the output:
|
||||
# "tail: '...' has appeared; following new file"
|
||||
tail_re='has appeared' retry_delay_ check_tail_output .1 7 ||
|
||||
{ echo "$0: a: unexpected delay?"; cat out; fail=1; }
|
||||
{ echo "$0: a: unexpected delay 2?"; cat out; fail=1; }
|
||||
# Wait up to 12.7s for "x2" to be displayed:
|
||||
file='a' data='x2' retry_delay_ check_tail_output .1 7 ||
|
||||
{ echo "$0: a: unexpected delay 2?"; cat out; fail=1; }
|
||||
{ echo "$0: a: unexpected delay 3?"; cat out; fail=1; }
|
||||
|
||||
echo y >> b
|
||||
# Wait up to 12.7s for "y" to appear in the output:
|
||||
file='b' data='y' retry_delay_ check_tail_output .1 7 ||
|
||||
{ echo "$0: b: unexpected delay 2?"; cat out; fail=1; }
|
||||
{ echo "$0: b: unexpected delay 4?"; cat out; fail=1; }
|
||||
|
||||
echo z >> a
|
||||
# Wait up to 12.7s for "z" to appear in the output:
|
||||
file='a' data='z' retry_delay_ check_tail_output .1 7 ||
|
||||
{ echo "$0: a: unexpected delay 3?"; cat out; fail=1; }
|
||||
{ echo "$0: a: unexpected delay 5?"; cat out; fail=1; }
|
||||
|
||||
cleanup_
|
||||
done
|
||||
|
||||
@@ -23,13 +23,20 @@ cat <<\EOF > exp || framework_failure_
|
||||
tail: cannot open 'no-such' for reading: No such file or directory
|
||||
tail: no files remaining
|
||||
EOF
|
||||
|
||||
returns_ 1 timeout 10 tail --follow=name no-such > out 2> err || fail=1
|
||||
|
||||
# Remove an inconsequential inotify warning so
|
||||
# we can compare against the above error
|
||||
sed '/inotify cannot be used/d' err > k && mv k err
|
||||
|
||||
compare exp err || fail=1
|
||||
|
||||
# Between coreutils 8.34 and 9.5 inclusive, tail would have
|
||||
# waited indefinitely when a file was moved to the same file system
|
||||
cleanup_() { kill $pid 2>/dev/null && wait $pid; }
|
||||
touch file || framework_failure_
|
||||
timeout 10 tail --follow=name file & pid=$!
|
||||
sleep .1 # Usually in inotify loop here
|
||||
mv file file.unfollow || framework_failure_
|
||||
wait $pid
|
||||
test $? = 1 || fail=1
|
||||
|
||||
Exit $fail
|
||||
|
||||
Reference in New Issue
Block a user