• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // commit 76ca7a5446a8aec2b671a401d5e1878c4704754e
2 // pthread_cond_wait should act on cancellation arriving after unlocking mutex
3 
4 #include <pthread.h>
5 #include <errno.h>
6 #include <time.h>
7 
8 #include "test.h"
9 
10 static pthread_mutex_t mx = PTHREAD_MUTEX_INITIALIZER;
11 static pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
12 static int waiting;
13 
cleanup(void * p)14 static void cleanup(void *p)
15 {
16 	waiting = 0;
17 	pthread_cond_signal(&cv);
18 	pthread_mutex_unlock(&mx);
19 }
20 
waiter(void * p)21 static void *waiter(void *p)
22 {
23 	pthread_mutex_lock(&mx);
24 	waiting = 1;
25 	pthread_cond_signal(&cv);
26 	pthread_cleanup_push(cleanup, 0);
27 	while (waiting) pthread_cond_wait(&cv, &mx);
28 	pthread_cleanup_pop(1);
29 	return 0;
30 }
31 
main(void)32 int main(void)
33 {
34 	pthread_t td;
35 	struct timespec ts;
36 	void *rv;
37 	pthread_mutex_lock(&mx);
38 	pthread_create(&td, 0, waiter, 0);
39 	while (!waiting) pthread_cond_wait(&cv, &mx);
40 	pthread_cancel(td);
41 	clock_gettime(CLOCK_REALTIME, &ts);
42 	if ((ts.tv_nsec+=30000000) >= 1000000000) {
43 		ts.tv_sec++;
44 		ts.tv_nsec -= 1000000000;
45 	}
46 	while (waiting && !pthread_cond_timedwait(&cv, &mx, &ts));
47 	waiting = 0;
48 	pthread_cond_signal(&cv);
49 	pthread_mutex_unlock(&mx);
50 	pthread_join(td, &rv);
51 	if (rv != PTHREAD_CANCELED)
52 		t_error("pthread_cond_wait did not act on cancellation\n");
53 	return t_status;
54 }
55