1 #include <pthread.h>
2 #include <signal.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <internal-signals.h>
6
7
8 static pthread_barrier_t b;
9 static pthread_t th2;
10
11
12 static void *
tf2(void * arg)13 tf2 (void *arg)
14 {
15 sigset_t mask;
16 if (pthread_sigmask (SIG_SETMASK, NULL, &mask) != 0)
17 {
18 puts ("pthread_sigmask failed");
19 exit (1);
20 }
21 #ifdef SIGCANCEL
22 if (sigismember (&mask, SIGCANCEL))
23 {
24 puts ("SIGCANCEL blocked in new thread");
25 exit (1);
26 }
27 #endif
28
29 /* Sync with the main thread so that we do not test anything else. */
30 int e = pthread_barrier_wait (&b);
31 if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
32 {
33 puts ("barrier_wait failed");
34 exit (1);
35 }
36
37 while (1)
38 {
39 /* Just a cancelable call. */
40 struct timespec ts = { 10000, 0 };
41 nanosleep (&ts, 0);
42 }
43
44 return NULL;
45 }
46
47
48 static void
unwhand(void * arg)49 unwhand (void *arg)
50 {
51 if (pthread_create (&th2, NULL, tf2, NULL) != 0)
52 {
53 puts ("unwhand: create failed");
54 exit (1);
55 }
56 }
57
58
59 static void *
tf(void * arg)60 tf (void *arg)
61 {
62 pthread_cleanup_push (unwhand, NULL);
63
64 /* Sync with the main thread so that we do not test anything else. */
65 int e = pthread_barrier_wait (&b);
66 if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
67 {
68 puts ("barrier_wait failed");
69 exit (1);
70 }
71
72 while (1)
73 {
74 /* Just a cancelable call. */
75 struct timespec ts = { 10000, 0 };
76 nanosleep (&ts, 0);
77 }
78
79 pthread_cleanup_pop (0);
80
81 return NULL;
82 }
83
84
85 static int
do_test(void)86 do_test (void)
87 {
88 if (pthread_barrier_init (&b, NULL, 2) != 0)
89 {
90 puts ("barrier_init failed");
91 return 1;
92 }
93
94 pthread_t th1;
95 if (pthread_create (&th1, NULL, tf, NULL) != 0)
96 {
97 puts ("create failed");
98 return 1;
99 }
100
101 int e = pthread_barrier_wait (&b);
102 if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
103 {
104 puts ("barrier_wait failed");
105 return 1;
106 }
107
108 /* Make sure tf1 enters nanosleep. */
109 struct timespec ts = { 0, 500000000 };
110 while (nanosleep (&ts, &ts) != 0)
111 ;
112
113 if (pthread_cancel (th1) != 0)
114 {
115 puts ("1st cancel failed");
116 return 1;
117 }
118
119 void *res;
120 if (pthread_join (th1, &res) != 0)
121 {
122 puts ("1st join failed");
123 return 1;
124 }
125 if (res != PTHREAD_CANCELED)
126 {
127 puts ("1st thread not canceled");
128 return 1;
129 }
130
131 e = pthread_barrier_wait (&b);
132 if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
133 {
134 puts ("barrier_wait failed");
135 return 1;
136 }
137
138 /* Make sure tf2 enters nanosleep. */
139 ts.tv_sec = 0;
140 ts.tv_nsec = 500000000;
141 while (nanosleep (&ts, &ts) != 0)
142 ;
143
144 puts ("calling pthread_cancel the second time");
145 if (pthread_cancel (th2) != 0)
146 {
147 puts ("2nd cancel failed");
148 return 1;
149 }
150
151 puts ("calling pthread_join the second time");
152 if (pthread_join (th2, &res) != 0)
153 {
154 puts ("2nd join failed");
155 return 1;
156 }
157 if (res != PTHREAD_CANCELED)
158 {
159 puts ("2nd thread not canceled");
160 return 1;
161 }
162
163 if (pthread_barrier_destroy (&b) != 0)
164 {
165 puts ("barrier_destroy failed");
166 return 0;
167 }
168
169 return 0;
170 }
171
172 #define TEST_FUNCTION do_test ()
173 #include "../test-skeleton.c"
174