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