| sort | uniq -u | grep . && { echo "$(ME): the above test(s)"\
" should match require_ulimit_v_ with ulimit -v" 1>&2; exit 1; } || :
+# Ensure that tests call the cleanup_ function if using background processes
+sc_prohibit_test_background_without_cleanup_:
+ @(git grep -El '( &$$|&[^&]*=\$$!)' tests; \
+ git grep -l 'cleanup_()' tests | sed p) \
+ | sort | uniq -u | grep . && { echo "$(ME): the above test(s)"\
+ " should use cleanup_ for background processes" 1>&2; exit 1; } || :
+
# Ensure that tests call the print_ver_ function for programs which are
# actually used in that test.
sc_prohibit_test_calls_print_ver_with_irrelevant_argument:
chgrp $g2 fifo-copy &&
chmod g+r fifo-copy || framework-failure
+# Terminate any background cp process
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
# Copy a fifo's contents. That way, we can examine the
# destination permissions before they're finalized.
-cp -p --copy-contents fifo fifo-copy &
-cp_pid=$!
+cp -p --copy-contents fifo fifo-copy & pid=$!
(
# Now 'cp' is reading the fifo. Wait for the destination file to
*) fail=1;;
esac
-wait $cp_pid || fail=1
+wait $pid || fail=1
# Check that the final mode and group are right.
ls -l -n fifo-copy >ls.out &&
umask 022
mkfifo_or_skip_ fifo
+# Terminate any background cp process
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
# Copy a fifo's contents. That way, we can examine the
# destination permissions before they're finalized.
-cp -p --copy-contents fifo fifo-copy &
-cp_pid=$!
+cp -p --copy-contents fifo fifo-copy & pid=$!
(
# Now 'cp' is reading the fifo. Wait for the destination file to
*) fail=1;;
esac
-wait $cp_pid || fail=1
+wait $pid || fail=1
Exit $fail
mkdir mode ownership d || framework_failure_
chmod g+s d 2>/dev/null # The cp test is valid either way.
+# Terminate any background cp process
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
for attr in mode ownership
do
# Copy a fifo's contents. That way, we can examine d/$attr's
# state while cp is running.
- cp --preserve=$attr -R --copy-contents --parents $attr d &
- cp_pid=$!
+ cp --preserve=$attr -R --copy-contents --parents $attr d & pid=$!
(
# Now 'cp' is reading the fifo.
fail=1;;
esac
- wait $cp_pid || fail=1
+ wait $pid || fail=1
done
Exit $fail
require_sparse_support_
+# Terminate any background cp process
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
mkfifo_or_skip_ pipe
-timeout 10 cat pipe > copy &
+timeout 10 cat pipe > copy & pid=$!
truncate -s1M sparse || framework_failure_
cp sparse pipe || fail=1
# Ensure that the cat has completed before comparing.
-wait
+wait $pid
cmp sparse copy || fail=1
mkfifo_or_skip_ fifo
+# Terminate any background processes
+cleanup_()
+{
+ kill $pid 2>/dev/null
+ kill $pid2 2>/dev/null
+ wait
+}
+
for open in '' '1'; do
# Run dd with the fullblock iflag to avoid short reads
# which can be triggered by reception of signals
# dd will block on open until fifo is opened for reading.
# Timeout in case dd goes away erroneously which we check for below.
- timeout 10 sh -c 'wc -c < fifo > nwritten' &
+ timeout 10 sh -c 'wc -c < fifo > nwritten' & pid2=$!
# Send lots of signals immediately to ensure dd not killed due
# to race setting handler, or blocking on open of fifo.
mkdir -p $t/3/a/b/c/$i/$long || framework_failure_
done
+# Terminate any background cp process
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
# Prohibit suspension, which could otherwise cause a timeout-induced FP failure.
trap '' TSTP
-timeout 6 ./inotify-watch-for-dir-access.py $t/3/a/b > start-msg &
+timeout 6 ./inotify-watch-for-dir-access.py $t/3/a/b > start-msg & pid=$!
# Wait for the watcher to start...
nonempty() { test -s start-msg || { sleep $1; return 1; }; }
# write separately.
mkfifo_or_skip_ fifo
+# Terminate any background cp process
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
echo 1 > exp
{
local delay="$1"
- dd count=1 if=fifo > out &
+ dd count=1 if=fifo > out & pid=$!
(echo 1; sleep $delay; echo 2) | cat -v > fifo
- wait # for dd to complete
+ wait $pid
compare exp out
}
. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+# Terminate any background processes
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
expected_failure_status_chroot=125
expected_failure_status_env=125
expected_failure_status_nice=125
# Use env to avoid invoking built-in sleep of Solaris 11's /bin/sh.
kill_setup () {
- env sleep 31.5 &
- args=$!
+ env sleep 10m & pid=$!
+ args=$pid
}
link_setup () { args="$tmp_in link-target"; }
# http://bugs.debian.org/481543#77
export MALLOC_PERTURB_=0
-head -c 10 fifo > out &
+# Terminate any background process
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
+head -c 10 fifo > out & pid=$!
# Choosing the virtual memory limit, 11000 is enough, but 10000 is too
# little and provokes a "memory exhausted" diagnostic on FreeBSD 9.0-p3.
print_ver_ sort
expensive_
+# Terminate any background processes
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
SORT_FAILURE=2
seq -w 2000 > exp || fail=1
# Ignore a random child process created before 'sort' was exec'ed.
# This bug was also present in coreutils 8.7.
#
-( (sleep 1; exec false) &
+( (sleep 1; exec false) & pid=$!
PRE_COMPRESS='test -f ok || sleep 2'
POST_COMPRESS='touch ok'
exec sort --compress-program=./compress -S 1k in >out
grep '^#define HAVE_PTHREAD_T 1' "$CONFIG_HEADER" > /dev/null ||
skip_ 'requires pthreads'
+# Terminate any background processes
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
seq 100000 > in || framework_failure_
mkfifo_or_skip_ fifo
# Arrange for sort to require 8.0+ seconds of wall-clock time,
# while actually using far less than 1 second of CPU time.
(for i in $(seq 80); do read line; echo $i; sleep .1; done
- cat > /dev/null) < fifo &
+ cat > /dev/null) < fifo & pid=$!
# However, under heavy load, it can easily take more than
# one second of CPU time, so set a permissive limit:
stdbuf -o1 no_such # no such command
test $? = 127 || fail=1
+# Terminate any background processes
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
# Ensure line buffering stdout takes effect
stdbuf_linebuffer()
{
local delay="$1"
printf '1\n' > exp
- dd count=1 if=fifo > out 2> err &
+ dd count=1 if=fifo > out 2> err & pid=$!
(printf '1\n'; sleep $delay; printf '2\n') | stdbuf -oL uniq > fifo
- wait # for dd to complete
+ wait $pid
compare exp out
}
# Ensure un buffering stdout takes effect
printf '1\n' > exp
- dd count=1 if=fifo > out 2> err &
+ dd count=1 if=fifo > out 2> err & pid=$!
(printf '1\n'; sleep $delay; printf '2\n') | stdbuf -o0 uniq > fifo
- wait # for dd to complete
+ wait $pid
compare exp out
}
fi
fp_tmp="$FULL_PARTITION_TMPDIR/tac-cont-$$"
-cleanup_() { rm -f "$fp_tmp"; }
+cleanup_()
+{
+ # Terminate any background process
+ # and remove tmp dir
+ rm -f "$fp_tmp"
+ kill $pid 2>/dev/null && wait $pid
+}
# Make sure we can create an empty file there (i.e., no shortage of inodes).
if ! touch $fp_tmp; then
# Give tac a fifo command line argument.
# This makes it try to create a temporary file in $TMPDIR.
mkfifo_or_skip_ fifo
-seq 1000 > fifo &
+seq 1000 > fifo & pid=$!
TMPDIR=$FULL_PARTITION_TMPDIR tac fifo in >out 2>err && fail=1
cat <<\EOF > exp || fail=1
{ sleep $delay; return 1; }
}
+# Terminate any background processes
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
# Start above script in its own group.
# We could use timeout for this, but that assumes an implementation.
-setsid ./group.sh &
+setsid ./group.sh & pid=$!
# Wait 6.3s for timeout.cmd to start
retry_delay_ check_timeout_cmd_running .1 6 || fail=1
# Simulate a Ctrl-C to the group to test timely exit
# Note dash doesn't support signalling groups (a leading -)
-env kill -INT -- -$!
+env kill -INT -- -$pid
wait
test -e int.received || fail=1
# Note the first timeout must send a signal that
# the second is handling for it to be propagated to the command.
# SIGINT, SIGTERM, SIGALRM etc. are implicit.
-timeout -sALRM 30 timeout -sINT 25 ./timeout.cmd 20&
-pid=$!
+timeout -sALRM 30 timeout -sINT 25 ./timeout.cmd 20 & pid=$!
# Wait 6.3s for timeout.cmd to start
retry_delay_ check_timeout_cmd_running .1 6 || fail=1
kill -ALRM $pid # trigger the alarm of the first timeout command
test -r "$tty" 2>&1 \
|| skip_ '/dev/stdin is not readable'
+# Terminate any background processes
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
mv f g < $tty > out 2>&1 & pid=$!
# Test for the expected prompt; sleep upon non-match.
# Wait for up to 12.7 seconds for the expected prompt.
retry_delay_ check_overwrite_prompt .1 7 || { fail=1; cat out; }
-kill $pid
+cleanup_
mv -f h i > out 2>&1 || fail=1
test -f i || fail=1
ln -s no-file dangle
ln -s / symlink
+# Terminate any background processes
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
-rm ---presume-input-tty dangle symlink &
-pid=$!
+rm ---presume-input-tty dangle symlink & pid=$!
# The buggy rm (fileutils-4.1.9) would hang here, waiting for input.
# Wait up to 3.1s for rm to remove the files
}
retry_delay_ check_files_removed .1 5 || fail=1
-kill $pid > /dev/null 2>&1
+cleanup_
Exit $fail
ls /dev/stdin >/dev/null 2>&1 \
|| skip_ 'there is no /dev/stdin file'
+# Terminate any background processes
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
touch f
chmod 0 f
-rm ---presume-input-tty f > out 2>&1 &
-pid=$!
+rm ---presume-input-tty f > out 2>&1 & pid=$!
# Wait a second, to give a buggy rm (as in fileutils-4.0.40)
# enough time to remove the file.
# The file must still exist.
test -f f || fail=1
-kill $pid > /dev/null 2>&1
+cleanup_
# Note the trailing 'x' -- so I don't have to have a trailing
# blank in this file :-)
{ sleep $delay; return 1; }
}
+# Terminate any background tail process
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
# Speedup the non inotify case
fastpoll='-s.1 --max-unchanged-stats=1'
tail_re='has appeared' retry_delay_ check_tail_output .1 7 ||
{ echo "$0: file: unexpected delay?"; cat out; fail=1; }
- kill $pid
-
- wait $pid
+ cleanup_
done
{ sleep $delay; return 1; }
}
+# Terminate any background tail process
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
# Speedup the non inotify case
fastpoll='-s.1 --max-unchanged-stats=1'
retry_delay_ tail_f_vs_rename_3 .1 7 ||
{ echo "$0: a: unexpected delay?"; cat out; fail=1; }
- kill $pid
-
- wait $pid
+ cleanup_
done
Exit $fail
print_ver_ tail
require_root_
+# Terminate any background tail process
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
chattr_a_works=1
touch f
chattr +a f 2>/dev/null || chattr_a_works=0
for mode in '' '---disable-inotify'; do
sleep 1 & pid=$!
tail --pid=$pid -f $mode f || fail=1
+ cleanup_
done
chattr -a f 2>/dev/null
{ sleep $delay; return 1; }
}
+# Terminate any background tail process
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
# Speedup the non inotify case
fastpoll='-s.1 --max-unchanged-stats=1'
-
for mode in '' '---disable-inotify'; do
rm -f a foo out
touch a || framework_failure_
# 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; }
+ { cat out; fail=1; break; }
# 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; }
+ { echo "$0: foo: unexpected delay?"; cat out; fail=1; break; }
- kill $pid
- wait $pid
+ cleanup_
done
Exit $fail
{ sleep $delay; return 1; }
}
+# Terminate any background tail process
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
# Speedup the non inotify case
fastpoll='-s.1 --max-unchanged-stats=1'
-
for mode in '' '---disable-inotify'; do
rm -f a foo out
touch a foo || framework_failure_
# 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; }
+ { cat out; fail=1; break; }
# 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; }
+ { cat out; fail=1; break; }
# 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; }
+ { echo "$0: foo: unexpected delay?"; cat out; fail=1; break; }
- kill $pid
- wait $pid
+ cleanup_
done
Exit $fail
{ sleep $delay; return 1; }
}
+# Terminate any background tail process
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
# Speedup the non inotify case
fastpoll='-s.1 --max-unchanged-stats=1'
# Wait up to 12.7s for "y" to appear in the output:
tail_re='^y$' retry_delay_ check_tail_output .1 7 || { cat out; fail=1; }
- kill $pid
-
- wait $pid
+ cleanup_
done
Exit $fail
# Speedup the non inotify case
fastpoll='-s.1 --max-unchanged-stats=1'
+# Terminate any background tail process
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
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 $fastpoll -f in > out & tail_pid=$!
+tail $fastpoll -f in > out & pid=$!
# Wait for 3.1s for the file to be flushed.
tail_flush()
}
retry_delay_ tail_flush .1 5 || fail=1
-kill $tail_pid
-
-wait $tail_pid
+cleanup_
Exit $fail
{ sleep $delay; return 1; }
}
+# Terminate any background tail process
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
# Speedup the non inotify case
fastpoll='-s.1 --max-unchanged-stats=1'
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
+ # Double check that tail hasn't aborted
+ kill -0 $pid || fail=1
- wait $pid
+ cleanup_
done
. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
print_ver_ tail
+# Terminate any background tail process
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
# Speedup the non inotify case
fastpoll='-s.1 --max-unchanged-stats=1'
touch f
done
- # Kill the working tail, or fail if it has already aborted
- kill $pid || fail=1
+ # Ensure tail hasn't aborted
+ kill -0 $pid || fail=1
- wait $pid
+ cleanup_
done
Exit $fail
. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
print_ver_ tail
+# Terminate any background gdb/tail process
+cleanup_() {
+ kill $pid 2>/dev/null && wait $pid
+ kill $sleep 2>/dev/null && wait $sleep
+}
+
touch file || framework_failure_
touch tail.out || framework_failure_
--eval-command='shell echo never-seen-with-tail-7.5 >> file' \
--eval-command='continue' \
--eval-command='quit' \
- tail < /dev/null > /dev/null 2>&1 &
-pid=$!
+ tail < /dev/null > /dev/null 2>&1 & pid=$!
tail --pid=$pid -f tail.out | (read; kill $pid)
fail=1
}
+# Terminate any background tail process
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
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_
+
+# Note the timeout guard isn't strictly necessary here,
+# however without it strace will ignore SIGTERM.
+# strace does always honor SIGTERM with the -I2 option,
+# though that's not available on RHEL6 for example.
timeout 180 strace -e inotify_rm_watch -o strace.out \
tail -F $fastpoll k >> out 2>&1 & pid=$!
done
test "$reverted_to_polling_" = 1 && skip_ 'inotify resources already depleted'
-kill $pid
-wait $pid
+
+cleanup_
Exit $fail
# Wait up to 25.5 seconds for grep REGEXP 'out' to succeed.
grep_timeout() { tail_re="$1" retry_delay_ check_tail_output .1 8; }
+# Terminate any background tail process
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
cleanup_fail()
{
cat out
warn_ $1
- kill $pid
+ cleanup_
fail=1
}
# wait for "ok" to appear in 'out'
grep_timeout 'ok' || { cleanup_fail 'failed to detect echoed ok'; break; }
- kill $pid
+ cleanup_
done
-wait
Exit $fail
touch empty here || framework_failure_
+# Terminate any background tail process
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
for mode in '' '---disable-inotify'; do
# Use tail itself to create a background process to monitor,
timeout 1 tail -f -s.1 --pid=$pid $mode here
test $? = 124 || fail=1
- # Cleanup background process
- kill $pid
- wait $pid
+ cleanup_
# Ensure that tail --pid=PID exits with success status when PID is dead.
# Use an unlikely-to-be-live PID
echo 1 > fifo &
echo 1 > exp || framework_failure_
+# Terminate any background tail process
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
# Speedup the non inotify case
fastpoll='-s.1 --max-unchanged-stats=1'
compare exp out || fail=1
-# Kill the still-running tail, or fail if it's gone.
-kill $pid || fail=1
+# Ensure tail is still running
+kill -0 $pid || fail=1
-wait $pid
+cleanup_
Exit $fail
[ "$(countlines_)" -ge "$elc" ] || { sleep $delay; return 1; }
}
+# Terminate any background tail process
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
# Speedup the non inotify case
fastpoll='-s.1 --max-unchanged-stats=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
+cleanup_
# Expect 3 lines in the output file.
[ "$(countlines_)" = 3 ] || { fail=1; cat out; }
grep -F 'cannot open' out || { fail=1; cat out; }
echo "X" > missing || framework_failure_
# Wait for the expected output.
retry_delay_ wait4lines_ .1 6 4 || { cat out; fail=1; }
-kill $pid
-wait $pid
+cleanup_
# Expect 4 lines in the output file.
[ "$(countlines_)" = 4 ] || { fail=1; cat out; }
grep -F 'retry only effective for the initial open' out \
[ "$(countlines_)" -ge "$elc" ] || { sleep $delay; return 1; }
}
+# Terminate any background tail process
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
# speedup non inotify case
fastpoll='-s.1 --max-unchanged-stats=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
+cleanup_
# Expect 3 lines in the output file.
[ "$(countlines_)" = 3 ] || { fail=1; cat out; }
grep -F 'cannot open' out || { fail=1; cat out; }
echo "X2" > target2 || framework_failure_
# Wait for the expected output.
retry_delay_ wait4lines_ .1 6 4 || { cat out; fail=1; }
-kill $pid
-wait $pid
+cleanup_
# Expect 4 lines in the output file.
[ "$(countlines_)" = 4 ] || { fail=1; cat out; }
grep -F 'become inacce' out || { fail=1; cat out; }
tail -c0 unreadable || fail=1
tail -n0 unreadable || fail=1
+# Terminate any background tail process
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
for mode in '' '---disable-inotify'; do
for file in empty nonempty; do
for c_or_n in c n; do
# Wait up to 1.5s for tail to sleep
retry_delay_ tail_sleeping .1 4 ||
{ echo $0: process in unexpected state: $state >&2; fail=1; }
- kill $pid
- wait $pid
+ cleanup_
done
done
done
touch here || framework_failure_
{ touch unreadable && chmod a-r unreadable; } || framework_failure_
+# Terminate any background tail process
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
# speedup non inotify case
fastpoll='-s.1 --max-unchanged-stats=1'
sleep $delay
echo NO >> l
sleep $delay
- kill $pid
- wait $pid
+ cleanup_
rm -f k l
test -s tail.out