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