summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorPádraig Brady <P@draigBrady.com>2015-05-01 18:03:37 +0100
committerPádraig Brady <P@draigBrady.com>2015-05-11 14:41:17 +0100
commitfe02153e6475ae52f90cfccae1d1ba24baf35f9c (patch)
tree25006e80ac8a20eeebe3f402f4ceec6de74dc50e /tests
parent8ee3ca4bb96f61ed5fc12da1d751a29fec6f7979 (diff)
downloadcoreutils-fe02153e6475ae52f90cfccae1d1ba24baf35f9c.tar.xz
tests: avoid hung processes due to gdb SIGCONT handling
* tests/tail-2/inotify-race.sh: Add a `wait` to ensure that we reap all background gdb and tail processes. That resulted in the test hanging intermittently and upon investigation was due to gdb intermittently failing to terminate the child process due to receiving a SIGCONT signal. Therefore we avoid using timeout(1) which sends that signal, and instead rely on tail's inbuilt --pid monitoring on a background sleep process. Given this new implementation, the VERY_EXPENSIVE guard was removed. Related issues with this test hanging were previously discussed at: https://lists.gnu.org/archive/html/bug-coreutils/2009-12/msg00025.html
Diffstat (limited to 'tests')
-rwxr-xr-xtests/tail-2/inotify-race.sh40
1 files changed, 30 insertions, 10 deletions
diff --git a/tests/tail-2/inotify-race.sh b/tests/tail-2/inotify-race.sh
index 2b1655c48..d28f898b6 100755
--- a/tests/tail-2/inotify-race.sh
+++ b/tests/tail-2/inotify-race.sh
@@ -23,11 +23,6 @@
. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
print_ver_ tail
-# Don't run this test by default because sometimes it's skipped as noted below.
-# Also gdb has a bug in Debian's gdb-6.8-3 at least that causes it to not
-# cleanup and exit correctly when it receives a SIGTERM, thus hanging the test.
-very_expensive_
-
touch file || framework_failure_
touch tail.out || framework_failure_
@@ -37,29 +32,46 @@ case $(cat gdb.out) in
*) skip_ "can't run gdb";;
esac
+# Break on a line rather than a symbol, to cater for inline functions
break_src="$abs_top_srcdir/src/tail.c"
break_line=$(grep -n ^tail_forever_inotify "$break_src") || framework_failure_
break_line=$(echo "$break_line" | cut -d: -f1) || framework_failure_
+
+# Note we get tail to monitor a background sleep process
+# rather than using timeout(1), as timeout sends SIGCONT
+# signals to its monitored process, and gdb (7.9 at least)
+# has _intermittent_ issues with this.
+# Sending SIGCONT resulted in either delayed child termination,
+# or no child termination resulting in a hung test.
+# See https://sourceware.org/bugzilla/show_bug.cgi?id=18364
+
+env sleep 10 & sleep=$!
+
# See if gdb works and
# tail_forever_inotify is compiled and run
-timeout 10s gdb -nx --batch-silent \
+gdb -nx --batch-silent \
--eval-command="break $break_line" \
- --eval-command='run -f file' \
+ --eval-command="run --pid=$sleep -f file" \
--eval-command='quit' \
- tail < /dev/null > gdb.out 2>&1 || skip_ 'breakpoint not hit'
+ tail < /dev/null > gdb.out 2>&1
+
+kill $sleep || skip_ 'breakpoint not hit'
+wait $sleep
# FIXME: The above is seen to _intermittently_ fail with:
# warning: .dynamic section for "/lib/libc.so.6" is not at the expected address
# warning: difference appears to be caused by prelink, adjusting expectations
compare /dev/null gdb.out || skip_ "can't set breakpoints in tail"
+env sleep 10 & sleep=$!
+
# Run "tail -f file", stopping to append a line just before
# inotify initialization, and then continue. Before the fix,
# that just-appended line would never be output.
-timeout 10s gdb -nx --batch-silent \
+gdb -nx --batch-silent \
--eval-command="break $break_line" \
- --eval-command='run -f file >> tail.out' \
+ --eval-command="run --pid=$sleep -f file >> tail.out" \
--eval-command='shell echo never-seen-with-tail-7.5 >> file' \
--eval-command='continue' \
--eval-command='quit' \
@@ -68,6 +80,14 @@ pid=$!
tail --pid=$pid -f tail.out | (read; kill $pid)
+# gdb has a bug in Debian's gdb-6.8-3 at least that causes it to not
+# cleanup and exit correctly when it receives a SIGTERM, but
+# killing sleep, should cause the tail process and thus gdb to exit.
+kill $sleep
+wait $sleep
+
+wait $pid
+
compare /dev/null tail.out && fail=1
Exit $fail