aboutsummaryrefslogtreecommitdiff
path: root/tools/test/stress2/misc/pthread10.sh
diff options
context:
space:
mode:
Diffstat (limited to 'tools/test/stress2/misc/pthread10.sh')
-rwxr-xr-xtools/test/stress2/misc/pthread10.sh106
1 files changed, 106 insertions, 0 deletions
diff --git a/tools/test/stress2/misc/pthread10.sh b/tools/test/stress2/misc/pthread10.sh
new file mode 100755
index 000000000000..ddeab0f9bb57
--- /dev/null
+++ b/tools/test/stress2/misc/pthread10.sh
@@ -0,0 +1,106 @@
+#!/bin/sh
+
+# Original test scenario by nabijaczleweli@nabijaczleweli.xyz:
+# Bug 283101 - pthread_cancel() doesn't cancel a thread that's currently in pause()
+# Fixed by: 9f78c837d94f check_cancel: when in_sigsuspend, send SIGCANCEL unconditionally
+
+. ../default.cfg
+set -u
+prog=$(basename "$0" .sh)
+cat > /tmp/$prog.c <<EOF
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static void *
+thread(void *arg __unused)
+{
+ for(;;) {
+ pause();
+ printf("woke up from pause\n");
+ }
+}
+
+static void
+thread_cancel_and_join(pthread_t ptid)
+{
+ void *status = NULL;
+
+ if (pthread_cancel(ptid)) {
+ printf("pthread_cancel() failed\n");
+ exit(1);
+ }
+
+ (void) pthread_join(ptid, &status);
+ int error = (int)(uintptr_t)status;
+
+ if (error) {
+ if (status == PTHREAD_CANCELED) {
+ printf("pthread_cancel() succeeded\n");
+ } else {
+ printf("pthread_join() error (not PTHREAD_CANCELED)\n");
+ exit(1);
+ }
+ }
+}
+
+int
+main(void)
+{
+ // Empirically, I've noticed that either the hang occurs somewhere between
+ // 10 and 500 iterations, or it runs infinitely without ever hanging.
+ // Therefore, stopping at 500th iteration, and looping from a shell script.
+
+ // For quick results (usually under 10 minutes), invoke "./run" from a dozen
+ // consoles or GNU screen windows in parallel.
+
+ pid_t pid = getpid();
+
+ for (uint64_t iteration = 1; iteration <= 500; ++iteration) {
+ printf("PID %d, iteration %lu...", pid, iteration);
+
+ pthread_t ptid;
+ int err;
+
+ err = pthread_create(&ptid, NULL, thread, NULL);
+
+ if (err) {
+ printf("pthread_create() failed with error: %d\n", err);
+ return 1;
+ }
+
+ thread_cancel_and_join(ptid);
+
+ printf("OK\n");
+
+ // Tiny sleep
+ usleep(20000);
+ }
+}
+EOF
+mycc -o /tmp/$prog -Wall -Wextra -O2 /tmp/$prog.c -lpthread || exit 1
+(cd ../testcases/swap; ./swap -t 3m -i 20 > /dev/null) &
+sleep 5
+start=`date +%s`
+while [ $((`date +%s` - start)) -lt 180 ]; do
+ /tmp/$prog > /dev/null & pid=$!
+ t1=`date +%s`
+ while kill -0 $pid 2> /dev/null; do
+ if [ $((`date +%s` - t1)) -gt 180 ]; then
+ ps -lH $pid
+# exit 1 # For DEBUG
+ kill -9 $pid; s=1
+ echo fail
+ break 2
+ else
+ sleep 1
+ fi
+ done
+ wait $pid; s=$?
+ [ $s -ne 0 ] && break
+done
+while pkill swap; do :; done
+wait
+rm -f /tmp/$prog /tmp/$prog.c
+exit $s