xref: /freebsd/tools/test/stress2/misc/pthread10.sh (revision ef777be98543f7daae90bd123d4fc1ec4a54efc2)
1#!/bin/sh
2
3# Original test scenario by nabijaczleweli@nabijaczleweli.xyz:
4# Bug 283101 - pthread_cancel() doesn't cancel a thread that's currently in pause()
5# Fixed by: 9f78c837d94f check_cancel: when in_sigsuspend, send SIGCANCEL unconditionally
6
7. ../default.cfg
8set -u
9prog=$(basename "$0" .sh)
10cat > /tmp/$prog.c <<EOF
11#include <pthread.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <unistd.h>
15
16static void *
17thread(void *arg __unused)
18{
19	for(;;) {
20		pause();
21		printf("woke up from pause\n");
22	}
23}
24
25static void
26thread_cancel_and_join(pthread_t ptid)
27{
28	void *status = NULL;
29
30	if (pthread_cancel(ptid)) {
31		printf("pthread_cancel() failed\n");
32		exit(1);
33	}
34
35	(void) pthread_join(ptid, &status);
36	int error = (int)(uintptr_t)status;
37
38	if (error) {
39		if (status == PTHREAD_CANCELED) {
40			printf("pthread_cancel() succeeded\n");
41		} else {
42			printf("pthread_join() error (not PTHREAD_CANCELED)\n");
43			exit(1);
44		}
45	}
46}
47
48int
49main(void)
50{
51	// Empirically, I've noticed that either the hang occurs somewhere between
52	// 10 and 500 iterations, or it runs infinitely without ever hanging.
53	// Therefore, stopping at 500th iteration, and looping from a shell script.
54
55	// For quick results (usually under 10 minutes), invoke "./run" from a dozen
56	// consoles or GNU screen windows in parallel.
57
58	pid_t pid = getpid();
59
60	for (uint64_t iteration = 1; iteration <= 500; ++iteration) {
61		printf("PID %d, iteration %lu...", pid, iteration);
62
63		pthread_t ptid;
64		int err;
65
66		err = pthread_create(&ptid, NULL, thread, NULL);
67
68		if (err) {
69			printf("pthread_create() failed with error: %d\n", err);
70			return 1;
71		}
72
73		thread_cancel_and_join(ptid);
74
75		printf("OK\n");
76
77		// Tiny sleep
78		usleep(20000);
79	}
80}
81EOF
82mycc -o /tmp/$prog -Wall -Wextra -O2 /tmp/$prog.c -lpthread || exit 1
83(cd ../testcases/swap; ./swap -t 3m -i 20 > /dev/null) &
84sleep 5
85start=`date +%s`
86while [ $((`date +%s` - start)) -lt 180 ]; do
87	/tmp/$prog > /dev/null & pid=$!
88	t1=`date +%s`
89	while kill -0 $pid 2> /dev/null; do
90		if [ $((`date +%s` - t1)) -gt 180 ]; then
91			ps -lH $pid
92#			exit 1 # For DEBUG
93			kill -9 $pid; s=1
94			echo fail
95			break 2
96		else
97			sleep 1
98		fi
99	done
100	wait $pid; s=$?
101	[ $s -ne 0 ] && break
102done
103while pkill swap; do :; done
104wait
105rm -f /tmp/$prog /tmp/$prog.c
106exit $s
107