mirror of
git://git.sv.gnu.org/coreutils.git
synced 2026-04-10 22:24:12 +02:00
tests: fix races in and standardize the tail tests
* tests/tail-2/F-vs-missing.sh: Use standard "fastpoll" options (-s.1 --max-unchanged-stats=1) to speedup the non-inotify case. Add the non-inotify case to the test. `wait` on the background tail process to terminate which should avoid the need for the non standard `retry_delay_ cleanup ...` on NFS. * tests/tail-2/F-vs-rename.sh: Remove 'out' at the start of the loop, to avoid a race in checking its contents. Also ensure 'a' & 'b' files are present before the tail process starts. Use the standard "fastpoll" options as above. * tests/tail-2/f-vs-rename.sh: Likewise. * tests/tail-2/append-only.sh: Use more standard variable names. * tests/tail-2/flush-initial.sh: Use "fastpoll" options for non-inotify platforms. Also `wait` on the background tail to avoid stray processes and file cleanup issues on NFS. * tests/tail-2/inotify-hash-abuse.sh: Always run non-inotify case. Use "fastpoll" options. Use a more standard retry_delay_ instead of a hardcoded sleep loop. Add a `wait` on the background tail. * tests/tail-2/inotify-hash-abuse2.sh: Likewise. * tests/tail-2/inotify-rotate-resources.sh: Wait just on the specific tail $pid needed. * tests/tail-2/inotify-rotate.sh: Use "fastpoll" options. * tests/tail-2/pid.sh: Use standard variable names. Add a `wait` on the background tails. * tests/tail-2/pipe-f2.sh: Likewise. * tests/tail-2/tail-n0f.sh: Likewise. * tests/tail-2/retry.sh: Use "fastpoll" options. * tests/tail-2/symlink.sh: Likewise. * tests/tail-2/wait.sh: Likewise. Speedup by using sub second parameters to timeout(1). Improve the part ensuring that -F never follows a renamed file. * tests/tail-2/infloop-1.sh: Remove invalid test. tail(1) was not being passed the --pid=$yes_pid option, retry_delay_ wasn't used to avoid races, and yes could write huge files before being killed. * tests/local.mk: Remove the invalid test reference. * tests/tail-2/assert-2.sh: Rewrite using retry_delay_(). Since no longer hardcoding large delays, remove the VERY_EXPENSIVE tag. * tests/tail-2/assert.sh: Likewise.
This commit is contained in:
@@ -197,7 +197,6 @@ all_tests = \
|
||||
tests/rm/i-1.sh \
|
||||
tests/rm/i-never.sh \
|
||||
tests/rm/i-no-r.sh \
|
||||
tests/tail-2/infloop-1.sh \
|
||||
tests/rm/ignorable.sh \
|
||||
tests/rm/inaccessible.sh \
|
||||
tests/rm/interactive-always.sh \
|
||||
|
||||
@@ -21,10 +21,6 @@
|
||||
. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
|
||||
print_ver_ tail
|
||||
|
||||
debug='---disable-inotify'
|
||||
debug=
|
||||
tail $debug -F -s.1 missing/file > out 2>&1 & pid=$!
|
||||
|
||||
check_tail_output()
|
||||
{
|
||||
local delay="$1"
|
||||
@@ -32,33 +28,31 @@ check_tail_output()
|
||||
{ sleep $delay; return 1; }
|
||||
}
|
||||
|
||||
# Wait up to 12.7s for tail to start with diagnostic:
|
||||
# tail: cannot open 'missing/file' for reading: No such file or directory
|
||||
tail_re='cannot open' retry_delay_ check_tail_output .1 7 || fail=1
|
||||
# Speedup the non inotify case
|
||||
fastpoll='-s.1 --max-unchanged-stats=1'
|
||||
|
||||
mkdir missing || fail=1
|
||||
(cd missing && echo x > file)
|
||||
for mode in '' '---disable-inotify'; do
|
||||
rm -rf out missing
|
||||
|
||||
# Wait up to 12.7s for this to appear in the output:
|
||||
# "tail: '...' has appeared; following end of new file"
|
||||
tail_re='has appeared' retry_delay_ check_tail_output .1 7 ||
|
||||
{ echo "$0: file: unexpected delay?"; cat out; fail=1; }
|
||||
tail $mode -F $fastpoll missing/file > out 2>&1 & pid=$!
|
||||
|
||||
kill -HUP $pid
|
||||
# Wait up to 12.7s for tail to start with diagnostic:
|
||||
# tail: cannot open 'missing/file' for reading: No such file or directory
|
||||
tail_re='cannot open' retry_delay_ check_tail_output .1 7 ||
|
||||
{ cat out; fail=1; }
|
||||
|
||||
cleanup()
|
||||
{
|
||||
local delay="$1"
|
||||
rm -rf missing ||
|
||||
{ sleep $delay; return 1; }
|
||||
}
|
||||
mkdir missing || framework_failure_
|
||||
(cd missing && echo x > file) || framework_failure_
|
||||
|
||||
# Wait up to 12.7s for this to appear in the output:
|
||||
# "tail: '...' has appeared; following end of new file"
|
||||
tail_re='has appeared' retry_delay_ check_tail_output .1 7 ||
|
||||
{ echo "$0: file: unexpected delay?"; cat out; fail=1; }
|
||||
|
||||
kill $pid
|
||||
|
||||
wait $pid
|
||||
done
|
||||
|
||||
# Try repeatedly to remove the temporary directory.
|
||||
# This is normally unnecessary, because the containing directory will
|
||||
# be removed by code from init.sh. However, when this particular test
|
||||
# is run on an NFS-mounted volume, sometimes init.sh's cleanup code
|
||||
# fails because the directory is not yet really empty, perhaps because
|
||||
# the tail process (reading missing/file) is not yet killed.
|
||||
retry_delay_ cleanup .1 6
|
||||
|
||||
Exit $fail
|
||||
|
||||
@@ -28,20 +28,25 @@ check_tail_output()
|
||||
{ sleep $delay; return 1; }
|
||||
}
|
||||
|
||||
touch a b || framework_failure_
|
||||
# Speedup the non inotify case
|
||||
fastpoll='-s.1 --max-unchanged-stats=1'
|
||||
|
||||
for mode in '' '---disable-inotify'; do
|
||||
tail $mode -F -s.1 a b > out 2>&1 & pid=$!
|
||||
rm -f a b out
|
||||
touch a b || framework_failure_
|
||||
|
||||
tail $mode -F $fastpoll a b > out 2>&1 & pid=$!
|
||||
|
||||
# Wait up to 12.7s for tail to start.
|
||||
echo x > a
|
||||
tail_re='^x$' retry_delay_ check_tail_output .1 7 || fail=1
|
||||
tail_re='^x$' retry_delay_ check_tail_output .1 7 || { cat out; fail=1; }
|
||||
|
||||
mv a b || fail=1
|
||||
mv a b || framework_failure_
|
||||
|
||||
# Wait 12.7s for this diagnostic:
|
||||
# tail: 'a' has become inaccessible: No such file or directory
|
||||
tail_re='inaccessible' retry_delay_ check_tail_output .1 7 || fail=1
|
||||
tail_re='inaccessible' retry_delay_ check_tail_output .1 7 ||
|
||||
{ cat out; fail=1; }
|
||||
|
||||
echo x > a
|
||||
# Wait up to 12.7s for this to appear in the output:
|
||||
|
||||
@@ -32,10 +32,9 @@ if test $chattr_a_works = 0; then
|
||||
fi
|
||||
|
||||
|
||||
for inotify in ---disable-inotify ''; do
|
||||
sleep 1 &
|
||||
pid=$!
|
||||
tail --pid=$pid -f $inotify f || fail=1
|
||||
for mode in '' '---disable-inotify'; do
|
||||
sleep 1 & pid=$!
|
||||
tail --pid=$pid -f $mode f || fail=1
|
||||
done
|
||||
|
||||
chattr -a f 2>/dev/null
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
# This variant of 'assert' would get a UMR reliably in 2.0.9.
|
||||
# This variant of 'assert' would get a Uninit Mem Read reliably in 2.0.9.
|
||||
# Due to a race condition in the test, the 'assert' script would get
|
||||
# the UMR on Solaris only some of the time, and not at all on Linux/GNU.
|
||||
|
||||
@@ -21,29 +21,36 @@
|
||||
. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
|
||||
print_ver_ tail
|
||||
|
||||
# Not "expensive" per se, but sleeping for so long is annoying.
|
||||
very_expensive_
|
||||
check_tail_output()
|
||||
{
|
||||
local delay="$1"
|
||||
grep "$tail_re" out ||
|
||||
{ sleep $delay; return 1; }
|
||||
}
|
||||
|
||||
ok='ok ok ok'
|
||||
# Speedup the non inotify case
|
||||
fastpoll='-s.1 --max-unchanged-stats=1'
|
||||
|
||||
touch a
|
||||
tail --follow=name a foo > err 2>&1 &
|
||||
tail_pid=$!
|
||||
# Arrange for the tail process to die after 12 seconds.
|
||||
(sleep 12; kill $tail_pid) &
|
||||
echo $ok > f
|
||||
echo sleeping for 7 seconds...
|
||||
sleep 7
|
||||
mv f foo
|
||||
|
||||
# echo waiting....
|
||||
wait
|
||||
for mode in '' '---disable-inotify'; do
|
||||
rm -f a foo out
|
||||
touch a || framework_failure_
|
||||
|
||||
case "$(cat err)" in
|
||||
*$ok) ;;
|
||||
*) fail=1;;
|
||||
esac
|
||||
tail $mode --follow=name $fastpoll a foo > out 2>&1 & pid=$!
|
||||
|
||||
test $fail = 1 && cat err
|
||||
# Wait up to 12.7s for tail to start.
|
||||
echo x > a || framework_failure_
|
||||
tail_re='^x$' retry_delay_ check_tail_output .1 7 ||
|
||||
{ cat out; fail=1; }
|
||||
|
||||
# Wait up to 12.7s for tail to notice new foo file
|
||||
ok='ok ok ok'
|
||||
echo "$ok" > foo || framework_failure_
|
||||
tail_re="^$ok$" retry_delay_ check_tail_output .1 7 ||
|
||||
{ echo "$0: foo: unexpected delay?"; cat out; fail=1; }
|
||||
|
||||
kill $pid
|
||||
wait $pid
|
||||
done
|
||||
|
||||
Exit $fail
|
||||
|
||||
@@ -26,36 +26,42 @@
|
||||
. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
|
||||
print_ver_ tail
|
||||
|
||||
# Not "expensive" per se, but sleeping for so long is annoying.
|
||||
very_expensive_
|
||||
check_tail_output()
|
||||
{
|
||||
local delay="$1"
|
||||
grep "$tail_re" out ||
|
||||
{ sleep $delay; return 1; }
|
||||
}
|
||||
|
||||
ok='ok ok ok'
|
||||
# Speedup the non inotify case
|
||||
fastpoll='-s.1 --max-unchanged-stats=1'
|
||||
|
||||
touch a foo
|
||||
tail --follow=name a foo > err 2>&1 &
|
||||
tail_pid=$!
|
||||
# Arrange for the tail process to die after 12 seconds.
|
||||
(sleep 12; kill $tail_pid) &
|
||||
|
||||
echo sleeping for 7 seconds...
|
||||
for mode in '' '---disable-inotify'; do
|
||||
rm -f a foo out
|
||||
touch a foo || framework_failure_
|
||||
|
||||
# Give the backgrounded 'tail' a chance to start before removing foo.
|
||||
# Otherwise, without --retry, tail wouldn't try to open 'foo' again.
|
||||
sleep 1
|
||||
tail $mode --follow=name $fastpoll a foo > out 2>&1 & pid=$!
|
||||
|
||||
rm -f foo
|
||||
sleep 6
|
||||
echo $ok > f
|
||||
mv f foo
|
||||
# Wait up to 12.7s for tail to start.
|
||||
echo x > a || framework_failure_
|
||||
tail_re='^x$' retry_delay_ check_tail_output .1 7 ||
|
||||
{ cat out; fail=1; }
|
||||
|
||||
# echo waiting....
|
||||
wait
|
||||
# Wait 12.7s for this diagnostic:
|
||||
# tail: foo: No such file or directory
|
||||
rm foo || framework_failure_
|
||||
tail_re='No such file' retry_delay_ check_tail_output .1 7 ||
|
||||
{ cat out; fail=1; }
|
||||
|
||||
case "$(cat err)" in
|
||||
*$ok) ;;
|
||||
*) fail=1;;
|
||||
esac
|
||||
# Wait up to 12.7s for tail to notice new foo file
|
||||
ok='ok ok ok'
|
||||
echo "$ok" > foo || framework_failure_
|
||||
tail_re="^$ok$" retry_delay_ check_tail_output .1 7 ||
|
||||
{ echo "$0: foo: unexpected delay?"; cat out; fail=1; }
|
||||
|
||||
test $fail = 1 && cat err
|
||||
kill $pid
|
||||
wait $pid
|
||||
done
|
||||
|
||||
Exit $fail
|
||||
|
||||
@@ -28,20 +28,24 @@ check_tail_output()
|
||||
{ sleep $delay; return 1; }
|
||||
}
|
||||
|
||||
touch a || framework_failure_
|
||||
# Speedup the non inotify case
|
||||
fastpoll='-s.1 --max-unchanged-stats=1'
|
||||
|
||||
for mode in '' '---disable-inotify'; do
|
||||
tail $mode -f -s.1 a > out 2>&1 & pid=$!
|
||||
rm -f a out
|
||||
touch a || framework_failure_
|
||||
|
||||
tail $mode $fastpoll -f a > out 2>&1 & pid=$!
|
||||
|
||||
# Wait up to 12.7s for tail to start.
|
||||
echo x > a
|
||||
tail_re='^x$' retry_delay_ check_tail_output .1 7 || fail=1
|
||||
tail_re='^x$' retry_delay_ check_tail_output .1 7 || { cat out; fail=1; }
|
||||
|
||||
mv a b || fail=1
|
||||
mv a b || framework_failure_
|
||||
|
||||
echo y >> b
|
||||
# Wait up to 12.7s for "y" to appear in the output:
|
||||
tail_re='^y$' retry_delay_ check_tail_output .1 7 || fail=1
|
||||
tail_re='^y$' retry_delay_ check_tail_output .1 7 || { cat out; fail=1; }
|
||||
|
||||
kill $pid
|
||||
|
||||
|
||||
@@ -19,11 +19,13 @@
|
||||
. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
|
||||
print_ver_ tail
|
||||
|
||||
echo line > in || fail=1
|
||||
# Speedup the non inotify case
|
||||
fastpoll='-s.1 --max-unchanged-stats=1'
|
||||
|
||||
echo line > in || framework_failure_
|
||||
# Output should be buffered since we're writing to file
|
||||
# so we're depending on the flush to write out
|
||||
tail -f in > out &
|
||||
tail_pid=$!
|
||||
tail $fastpoll -f in > out & tail_pid=$!
|
||||
|
||||
# Wait for 3.1s for the file to be flushed.
|
||||
tail_flush()
|
||||
@@ -37,4 +39,6 @@ retry_delay_ tail_flush .1 5 || fail=1
|
||||
|
||||
kill $tail_pid
|
||||
|
||||
wait $tail_pid
|
||||
|
||||
Exit $fail
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
#!/bin/sh
|
||||
# This test would fail with tail from pre-1.22i textutils.
|
||||
|
||||
# Copyright (C) 1999-2015 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
|
||||
print_ver_ tail
|
||||
|
||||
yes > t &
|
||||
yes_pid=$!
|
||||
while :; do
|
||||
test -s t \
|
||||
&& break
|
||||
sleep .1
|
||||
done
|
||||
tail -n 1 t &
|
||||
tail_pid=$!
|
||||
kill $yes_pid
|
||||
|
||||
# This test is racy, and can fail under unusual circumstances.
|
||||
# On a very busy system, tail will fail to notice that $yes_pid is gone.
|
||||
# Then the following kill will succeed and cause this test to fail.
|
||||
|
||||
# Wait for up to 3 seconds for tail to detect the death of $yes_pid.
|
||||
for i in $(seq 30); do
|
||||
kill -0 $tail_pid || break
|
||||
echo sleep 0.1s
|
||||
sleep .1
|
||||
done
|
||||
|
||||
kill $tail_pid && fail=1 || :
|
||||
|
||||
Exit $fail
|
||||
@@ -23,10 +23,6 @@ print_ver_ tail
|
||||
n=9
|
||||
seq $n | xargs touch || framework_failure_
|
||||
|
||||
debug='---disable-inotify'
|
||||
debug=
|
||||
tail $debug -s.1 -qF $(seq $n) > out 2>&1 & pid=$!
|
||||
|
||||
check_tail_output()
|
||||
{
|
||||
local delay="$1"
|
||||
@@ -34,30 +30,39 @@ check_tail_output()
|
||||
{ sleep $delay; return 1; }
|
||||
}
|
||||
|
||||
# Wait up to 12.7s for tail to start
|
||||
echo x > $n
|
||||
tail_re='^x$' retry_delay_ check_tail_output .1 7 || fail=1
|
||||
# Speedup the non inotify case
|
||||
fastpoll='-s.1 --max-unchanged-stats=1'
|
||||
|
||||
mv 1 f || fail=1
|
||||
for mode in '' '---disable-inotify'; do
|
||||
rm -f out
|
||||
|
||||
# Wait 12.7s for this diagnostic:
|
||||
# tail: '1' has become inaccessible: No such file or directory
|
||||
tail_re='inaccessible' retry_delay_ check_tail_output .1 7 || fail=1
|
||||
tail $mode $fastpoll -qF $(seq $n) > out 2>&1 & pid=$!
|
||||
|
||||
# Trigger the bug. Before the fix, this would provoke the abort.
|
||||
echo a > 1 || fail=1
|
||||
# Wait up to 12.7s for tail to start
|
||||
echo x > $n
|
||||
tail_re='^x$' retry_delay_ check_tail_output .1 7 ||
|
||||
{ cat out; fail=1; }
|
||||
|
||||
# Wait up to 2s for the buggy tail to die,
|
||||
# or for the "tail: '1' has appeared; following end of new file" output
|
||||
for i in $(seq 10); do
|
||||
kill -0 $pid || break
|
||||
grep 'has appeared;' out > /dev/null && break
|
||||
sleep .2
|
||||
mv 1 f || framework_failure_
|
||||
|
||||
# Wait 12.7s for this diagnostic:
|
||||
# tail: '1' has become inaccessible: No such file or directory
|
||||
tail_re='inaccessible' retry_delay_ check_tail_output .1 7 ||
|
||||
{ cat out; fail=1; }
|
||||
|
||||
# Trigger the bug. Before the fix, this would provoke the abort.
|
||||
echo a > 1 || framework_failure_
|
||||
|
||||
# Wait up to 6.3s for the "tail: '1' has appeared; ..." message
|
||||
# (or for the buggy tail to die)
|
||||
tail_re='has appeared' retry_delay_ check_tail_output .1 6 ||
|
||||
{ cat out; fail=1; }
|
||||
|
||||
# Kill the working tail, or fail if it has already aborted
|
||||
kill $pid || fail=1
|
||||
|
||||
wait $pid
|
||||
done
|
||||
|
||||
# Kill the working tail, or fail if it has already aborted
|
||||
kill $pid || fail=1
|
||||
|
||||
cat out
|
||||
|
||||
Exit $fail
|
||||
|
||||
@@ -20,20 +20,24 @@
|
||||
. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
|
||||
print_ver_ tail
|
||||
|
||||
touch f || framework_failure_
|
||||
# Speedup the non inotify case
|
||||
fastpoll='-s.1 --max-unchanged-stats=1'
|
||||
|
||||
debug='---disable-inotify -s .001'
|
||||
debug=
|
||||
tail $debug -F f & pid=$!
|
||||
cleanup_() { kill $pid; }
|
||||
for mode in '' '---disable-inotify'; do
|
||||
touch f || framework_failure_
|
||||
|
||||
for i in $(seq 200); do
|
||||
kill -0 $pid || break;
|
||||
mv f g
|
||||
touch f
|
||||
tail $mode $fastpoll -F f & pid=$!
|
||||
|
||||
for i in $(seq 200); do
|
||||
kill -0 $pid || break;
|
||||
mv f g
|
||||
touch f
|
||||
done
|
||||
|
||||
# Kill the working tail, or fail if it has already aborted
|
||||
kill $pid || fail=1
|
||||
|
||||
wait $pid
|
||||
done
|
||||
|
||||
# Kill the working tail, or fail if it has already aborted
|
||||
kill $pid || fail=1
|
||||
|
||||
Exit $fail
|
||||
|
||||
@@ -34,10 +34,10 @@ check_tail_output()
|
||||
# Wait up to 25.5 seconds for grep REGEXP 'out' to succeed.
|
||||
grep_timeout() { tail_re="$1" retry_delay_ check_tail_output .1 8; }
|
||||
|
||||
strace_output()
|
||||
check_strace()
|
||||
{
|
||||
local delay="$1"
|
||||
test -s strace.out ||
|
||||
grep "$strace_re" strace.out > /dev/null ||
|
||||
{ sleep $delay; return 1; }
|
||||
}
|
||||
|
||||
@@ -48,13 +48,15 @@ cleanup_fail()
|
||||
fail=1
|
||||
}
|
||||
|
||||
fastpoll='-s.1 --max-unchanged-stats=1'
|
||||
|
||||
# Normally less than a second is required here, but with heavy load
|
||||
# and a lot of disk activity, even 20 seconds per grep_timeout is insufficient,
|
||||
# which leads to this timeout (used as a safety net for cleanup)
|
||||
# killing tail before processing is completed.
|
||||
touch k || framework_failure_
|
||||
timeout 180 strace -e inotify_rm_watch -o strace.out tail -F k >> out 2>&1 &
|
||||
pid=$!
|
||||
timeout 180 strace -e inotify_rm_watch -o strace.out \
|
||||
tail -F $fastpoll k >> out 2>&1 & pid=$!
|
||||
|
||||
reverted_to_polling_=0
|
||||
for i in $(seq 2); do
|
||||
@@ -82,7 +84,7 @@ for i in $(seq 2); do
|
||||
# may not be supported in future, instead being auto scaled to RAM
|
||||
# like the Linux epoll resources were.
|
||||
if test "$i" -gt 1; then
|
||||
retry_delay_ strace_output .1 8 ||
|
||||
strace_re='inotify_rm_watch' retry_delay_ check_strace .1 8 ||
|
||||
{ cleanup_fail 'failed to find inotify_rm_watch syscall'; break; }
|
||||
fi
|
||||
|
||||
@@ -91,6 +93,6 @@ done
|
||||
|
||||
test "$reverted_to_polling_" = 1 && skip_ 'inotify resources already depleted'
|
||||
kill $pid
|
||||
wait
|
||||
wait $pid
|
||||
|
||||
Exit $fail
|
||||
|
||||
@@ -40,6 +40,9 @@ cleanup_fail()
|
||||
fail=1
|
||||
}
|
||||
|
||||
# Speedup the non inotify case
|
||||
fastpoll='-s.1 --max-unchanged-stats=1'
|
||||
|
||||
# Perform at least this many iterations, because on multi-core systems
|
||||
# the offending sequence of events can be surprisingly uncommon.
|
||||
# See: http://lists.gnu.org/archive/html/bug-coreutils/2009-11/msg00213.html
|
||||
@@ -51,8 +54,7 @@ for i in $(seq 50); do
|
||||
# and a lot of disk activity, even 20 seconds is insufficient, which
|
||||
# leads to this timeout killing tail before the "ok" is written below.
|
||||
>k && >x || framework_failure_ failed to initialize files
|
||||
timeout 60 tail -s.1 --max-unchanged-stats=1 -F k > out 2>&1 &
|
||||
pid=$!
|
||||
timeout 60 tail $fastpoll -F k > out 2>&1 & pid=$!
|
||||
|
||||
echo 'tailed' > k;
|
||||
# wait for 'tailed' to appear in out
|
||||
|
||||
@@ -23,28 +23,28 @@ getlimits_
|
||||
touch empty here || framework_failure_
|
||||
|
||||
|
||||
for inotify in ---disable-inotify ''; do
|
||||
for mode in '' '---disable-inotify'; do
|
||||
# Use tail itself to create a background process to monitor,
|
||||
# which will auto exit when "here" is removed.
|
||||
tail -f $inotify here &
|
||||
bg_pid=$!
|
||||
tail -f $mode here & pid=$!
|
||||
|
||||
# Ensure that tail --pid=PID does not exit when PID is alive.
|
||||
timeout 1 tail -f -s.1 --pid=$bg_pid $inotify here
|
||||
timeout 1 tail -f -s.1 --pid=$pid $mode here
|
||||
test $? = 124 || fail=1
|
||||
|
||||
# Cleanup background process
|
||||
kill $bg_pid
|
||||
kill $pid
|
||||
wait $pid
|
||||
|
||||
# Ensure that tail --pid=PID exits with success status when PID is dead.
|
||||
# Use an unlikely-to-be-live PID
|
||||
timeout 10 tail -f -s.1 --pid=$PID_T_MAX $inotify empty
|
||||
timeout 10 tail -f -s.1 --pid=$PID_T_MAX $mode empty
|
||||
ret=$?
|
||||
test $ret = 124 && skip_ "pid $PID_T_MAX present or tail too slow"
|
||||
test $ret = 0 || fail=1
|
||||
|
||||
# Ensure tail doesn't wait for data when PID is dead
|
||||
timeout 10 tail -f -s10 --pid=$PID_T_MAX $inotify empty
|
||||
timeout 10 tail -f -s10 --pid=$PID_T_MAX $mode empty
|
||||
test $? = 124 && fail=1
|
||||
done
|
||||
|
||||
|
||||
@@ -24,7 +24,10 @@ mkfifo_or_skip_ fifo
|
||||
echo 1 > fifo &
|
||||
echo 1 > exp || framework_failure_
|
||||
|
||||
timeout 10 tail -f fifo > out & pid=$!
|
||||
# Speedup the non inotify case
|
||||
fastpoll='-s.1 --max-unchanged-stats=1'
|
||||
|
||||
timeout 10 tail $fastpoll -f fifo > out & pid=$!
|
||||
|
||||
check_tail_output()
|
||||
{
|
||||
@@ -40,4 +43,6 @@ compare exp out || fail=1
|
||||
# Kill the still-running tail, or fail if it's gone.
|
||||
kill $pid || fail=1
|
||||
|
||||
wait $pid
|
||||
|
||||
Exit $fail
|
||||
|
||||
@@ -36,27 +36,32 @@ wait4lines_ ()
|
||||
[ "$(countlines_)" -ge "$elc" ] || { sleep $delay; return 1; }
|
||||
}
|
||||
|
||||
# Speedup the non inotify case
|
||||
fastpoll='-s.1 --max-unchanged-stats=1'
|
||||
|
||||
# === Test:
|
||||
# Retry without --follow results in a warning.
|
||||
touch file
|
||||
tail --retry file > out 2>&1 || fail=1
|
||||
[ "$(countlines_)" = 1 ] || fail=1
|
||||
grep -F 'tail: warning: --retry ignored' out || fail=1
|
||||
[ "$(countlines_)" = 1 ] || { cat out; fail=1; }
|
||||
grep -F 'tail: warning: --retry ignored' out || { cat out; fail=1; }
|
||||
|
||||
# === Test:
|
||||
# The same with a missing file: expect error message and exit 1.
|
||||
tail --retry missing > out 2>&1 && fail=1
|
||||
[ "$(countlines_)" = 2 ] || fail=1
|
||||
grep -F 'tail: warning: --retry ignored' out || fail=1
|
||||
[ "$(countlines_)" = 2 ] || { cat out; fail=1; }
|
||||
grep -F 'tail: warning: --retry ignored' out || { cat out; fail=1; }
|
||||
|
||||
# === Test:
|
||||
# Ensure that "tail --retry --follow=name" waits for the file to appear.
|
||||
# Clear 'out' so that we can check its contents without races
|
||||
>out || framework_failure_
|
||||
timeout 10 tail -s.1 --follow=name --retry missing >out 2>&1 & pid=$!
|
||||
retry_delay_ wait4lines_ .1 6 1 || fail=1 # Wait for "cannot open" error.
|
||||
echo "X" > missing || fail=1
|
||||
retry_delay_ wait4lines_ .1 6 3 || fail=1 # Wait for the expected output.
|
||||
timeout 10 tail $fastpoll --follow=name --retry missing >out 2>&1 & pid=$!
|
||||
# Wait for "cannot open" error.
|
||||
retry_delay_ wait4lines_ .1 6 1 || { cat out; fail=1; }
|
||||
echo "X" > missing || framework_failure_
|
||||
# Wait for the expected output.
|
||||
retry_delay_ wait4lines_ .1 6 3 || { cat out; fail=1; }
|
||||
kill $pid
|
||||
wait $pid
|
||||
# Expect 3 lines in the output file.
|
||||
@@ -69,10 +74,12 @@ rm -f missing out || framework_failure_
|
||||
# === Test:
|
||||
# Ensure that "tail --retry --follow=descriptor" waits for the file to appear.
|
||||
# tail-8.21 failed at this (since the implementation of the inotify support).
|
||||
timeout 10 tail -s.1 --follow=descriptor --retry missing >out 2>&1 & pid=$!
|
||||
retry_delay_ wait4lines_ .1 6 2 || fail=1 # Wait for "cannot open" error.
|
||||
echo "X" > missing || fail=1
|
||||
retry_delay_ wait4lines_ .1 6 4 || fail=1 # Wait for the expected output.
|
||||
timeout 10 tail $fastpoll --follow=descriptor --retry missing >out 2>&1 & pid=$!
|
||||
# Wait for "cannot open" error.
|
||||
retry_delay_ wait4lines_ .1 6 2 || { cat out; fail=1; }
|
||||
echo "X" > missing || framework_failure_
|
||||
# Wait for the expected output.
|
||||
retry_delay_ wait4lines_ .1 6 4 || { cat out; fail=1; }
|
||||
kill $pid
|
||||
wait $pid
|
||||
# Expect 4 lines in the output file.
|
||||
@@ -87,10 +94,12 @@ rm -f missing out || framework_failure_
|
||||
# === Test:
|
||||
# Ensure that tail --follow=descriptor --retry exits when the file appears
|
||||
# untailable. Expect exit status 1.
|
||||
timeout 10 tail -s.1 --follow=descriptor --retry missing >out 2>&1 & pid=$!
|
||||
retry_delay_ wait4lines_ .1 6 2 || fail=1 # Wait for "cannot open" error.
|
||||
mkdir missing || fail=1 # Create untailable 'missing'.
|
||||
retry_delay_ wait4lines_ .1 6 4 || fail=1 # Wait for the expected output.
|
||||
timeout 10 tail $fastpoll --follow=descriptor --retry missing >out 2>&1 & pid=$!
|
||||
# Wait for "cannot open" error.
|
||||
retry_delay_ wait4lines_ .1 6 2 || { cat out; fail=1; }
|
||||
mkdir missing || framework_failure_ # Create untailable
|
||||
# Wait for the expected output.
|
||||
retry_delay_ wait4lines_ .1 6 4 || { cat out; fail=1; }
|
||||
wait $pid
|
||||
rc=$?
|
||||
[ "$(countlines_)" = 4 ] || { fail=1; cat out; }
|
||||
|
||||
@@ -36,15 +36,20 @@ wait4lines_ ()
|
||||
[ "$(countlines_)" -ge "$elc" ] || { sleep $delay; return 1; }
|
||||
}
|
||||
|
||||
# speedup non inotify case
|
||||
fastpoll='-s.1 --max-unchanged-stats=1'
|
||||
|
||||
# Ensure changing targets of cli specified symlinks are handled.
|
||||
# Prior to v8.22, inotify would fail to recognize changes in the targets.
|
||||
# Clear 'out' so that we can check its contents without races.
|
||||
>out || framework_failure_
|
||||
ln -nsf target symlink || framework_failure_
|
||||
timeout 10 tail -s.1 -F symlink >out 2>&1 & pid=$!
|
||||
retry_delay_ wait4lines_ .1 6 1 || fail=1 # Wait for "cannot open..."
|
||||
echo "X" > target || fail=1
|
||||
retry_delay_ wait4lines_ .1 6 3 || fail=1 # Wait for the expected output.
|
||||
timeout 10 tail $fastpoll -F symlink >out 2>&1 & pid=$!
|
||||
# Wait for "cannot open..."
|
||||
retry_delay_ wait4lines_ .1 6 1 || { cat out; fail=1; }
|
||||
echo "X" > target || framework_failure_
|
||||
# Wait for the expected output.
|
||||
retry_delay_ wait4lines_ .1 6 3 || { cat out; fail=1; }
|
||||
kill $pid
|
||||
wait $pid
|
||||
# Expect 3 lines in the output file.
|
||||
@@ -60,12 +65,15 @@ rm -f target out || framework_failure_
|
||||
>out || framework_failure_
|
||||
echo "X1" > target1 || framework_failure_
|
||||
ln -nsf target1 symlink || framework_failure_
|
||||
timeout 10 tail -s.1 -F symlink >out 2>&1 & pid=$!
|
||||
retry_delay_ wait4lines_ .1 6 1 || fail=1 # Wait for the expected output.
|
||||
timeout 10 tail $fastpoll -F symlink >out 2>&1 & pid=$!
|
||||
# Wait for the expected output.
|
||||
retry_delay_ wait4lines_ .1 6 1 || { cat out; fail=1; }
|
||||
ln -nsf target2 symlink || framework_failure_
|
||||
retry_delay_ wait4lines_ .1 6 2 || fail=1 # Wait for "become inaccess..."
|
||||
echo "X2" > target2 || fail=1
|
||||
retry_delay_ wait4lines_ .1 6 4 || fail=1 # Wait for the expected output.
|
||||
# Wait for "become inaccess..."
|
||||
retry_delay_ wait4lines_ .1 6 2 || { cat out; fail=1; }
|
||||
echo "X2" > target2 || framework_failure_
|
||||
# Wait for the expected output.
|
||||
retry_delay_ wait4lines_ .1 6 4 || { cat out; fail=1; }
|
||||
kill $pid
|
||||
wait $pid
|
||||
# Expect 4 lines in the output file.
|
||||
|
||||
@@ -35,11 +35,10 @@ chmod 0 unreadable || framework_failure_
|
||||
tail -c0 unreadable || fail=1
|
||||
tail -n0 unreadable || fail=1
|
||||
|
||||
for inotify in ---disable-inotify ''; do
|
||||
for mode in '' '---disable-inotify'; do
|
||||
for file in empty nonempty; do
|
||||
for c_or_n in c n; do
|
||||
tail --sleep=4 -${c_or_n} 0 -f $inotify $file &
|
||||
pid=$!
|
||||
tail --sleep=4 -${c_or_n} 0 -f $mode $file & pid=$!
|
||||
tail_sleeping()
|
||||
{
|
||||
local delay="$1"; sleep $delay
|
||||
@@ -53,6 +52,7 @@ for inotify in ---disable-inotify ''; do
|
||||
retry_delay_ tail_sleeping .1 4 ||
|
||||
{ echo $0: process in unexpected state: $state >&2; fail=1; }
|
||||
kill $pid
|
||||
wait $pid
|
||||
done
|
||||
done
|
||||
done
|
||||
|
||||
@@ -23,30 +23,32 @@ print_ver_ tail
|
||||
touch here || framework_failure_
|
||||
{ touch unreadable && chmod a-r unreadable; } || framework_failure_
|
||||
|
||||
# speedup non inotify case
|
||||
fastpoll='-s.1 --max-unchanged-stats=1'
|
||||
|
||||
for inotify in ---disable-inotify ''; do
|
||||
timeout 10 tail -s0.1 -f $inotify not_here
|
||||
for mode in '' '---disable-inotify'; do
|
||||
timeout 10 tail $fastpoll -f $mode not_here
|
||||
test $? = 124 && fail=1
|
||||
|
||||
if test ! -r unreadable; then # can't test this when root
|
||||
timeout 10 tail -s0.1 -f $inotify unreadable
|
||||
timeout 10 tail $fastpoll -f $mode unreadable
|
||||
test $? = 124 && fail=1
|
||||
fi
|
||||
|
||||
timeout 1 tail -s0.1 -f $inotify here 2>tail.err
|
||||
timeout .1 tail $fastpoll -f $mode here 2>tail.err
|
||||
test $? = 124 || fail=1
|
||||
|
||||
# 'tail -F' must wait in any case.
|
||||
|
||||
timeout 1 tail -s0.1 -F $inotify here 2>>tail.err
|
||||
timeout .1 tail $fastpoll -F $mode here 2>>tail.err
|
||||
test $? = 124 || fail=1
|
||||
|
||||
if test ! -r unreadable; then # can't test this when root
|
||||
timeout 1 tail -s0.1 -F $inotify unreadable
|
||||
timeout .1 tail $fastpoll -F $mode unreadable
|
||||
test $? = 124 || fail=1
|
||||
fi
|
||||
|
||||
timeout 1 tail -s0.1 -F $inotify not_here
|
||||
timeout .1 tail $fastpoll -F $mode not_here
|
||||
test $? = 124 || fail=1
|
||||
|
||||
grep -Ev 'inotify (resources exhausted|cannot be used)' tail.err > x
|
||||
@@ -54,13 +56,14 @@ for inotify in ---disable-inotify ''; do
|
||||
compare /dev/null tail.err || fail=1
|
||||
>tail.err
|
||||
|
||||
# Ensure -F never follows a descriptor after rename
|
||||
# either with tiny or significant delays between operations
|
||||
tail_F()
|
||||
{
|
||||
local delay="$1"
|
||||
|
||||
touch k || framework_failure_
|
||||
tail -s.1 --max-unchanged-stats=2 -F $inotify k > tail.out &
|
||||
pid=$!
|
||||
tail $fastpoll -F $mode k > tail.out & pid=$!
|
||||
sleep $delay
|
||||
mv k l
|
||||
sleep $delay
|
||||
@@ -70,11 +73,13 @@ for inotify in ---disable-inotify ''; do
|
||||
echo NO >> l
|
||||
sleep $delay
|
||||
kill $pid
|
||||
wait $pid
|
||||
rm -f k l
|
||||
|
||||
test ! -s tail.out
|
||||
test -s tail.out
|
||||
}
|
||||
retry_delay_ tail_F .1 4 || fail=1
|
||||
retry_delay_ tail_F 0 1 && { cat tail.out; fail=1; }
|
||||
retry_delay_ tail_F .2 1 && { cat tail.out; fail=1; }
|
||||
done
|
||||
|
||||
Exit $fail
|
||||
|
||||
Reference in New Issue
Block a user