1#include <pthread.h>
2#include <signal.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <internal-signals.h>
6
7
8static pthread_barrier_t b;
9static pthread_t th2;
10
11
12static void *
13tf2 (void *arg)
14{
15 sigset_t mask;
16 if (pthread_sigmask (SIG_SETMASK, NULL, oldmask: &mask) != 0)
17 {
18 puts (s: "pthread_sigmask failed");
19 exit (1);
20 }
21#ifdef SIGCANCEL
22 if (sigismember (&mask, SIGCANCEL))
23 {
24 puts (s: "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 (barrier: &b);
31 if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
32 {
33 puts (s: "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 (requested_time: &ts, remaining: 0);
42 }
43
44 return NULL;
45}
46
47
48static void
49unwhand (void *arg)
50{
51 if (pthread_create (newthread: &th2, NULL, start_routine: tf2, NULL) != 0)
52 {
53 puts (s: "unwhand: create failed");
54 exit (1);
55 }
56}
57
58
59static void *
60tf (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 (barrier: &b);
66 if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
67 {
68 puts (s: "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 (requested_time: &ts, remaining: 0);
77 }
78
79 pthread_cleanup_pop (0);
80
81 return NULL;
82}
83
84
85static int
86do_test (void)
87{
88 if (pthread_barrier_init (barrier: &b, NULL, count: 2) != 0)
89 {
90 puts (s: "barrier_init failed");
91 return 1;
92 }
93
94 pthread_t th1;
95 if (pthread_create (newthread: &th1, NULL, start_routine: tf, NULL) != 0)
96 {
97 puts (s: "create failed");
98 return 1;
99 }
100
101 int e = pthread_barrier_wait (barrier: &b);
102 if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
103 {
104 puts (s: "barrier_wait failed");
105 return 1;
106 }
107
108 /* Make sure tf1 enters nanosleep. */
109 struct timespec ts = { 0, 500000000 };
110 while (nanosleep (requested_time: &ts, remaining: &ts) != 0)
111 ;
112
113 if (pthread_cancel (th: th1) != 0)
114 {
115 puts (s: "1st cancel failed");
116 return 1;
117 }
118
119 void *res;
120 if (pthread_join (th: th1, thread_return: &res) != 0)
121 {
122 puts (s: "1st join failed");
123 return 1;
124 }
125 if (res != PTHREAD_CANCELED)
126 {
127 puts (s: "1st thread not canceled");
128 return 1;
129 }
130
131 e = pthread_barrier_wait (barrier: &b);
132 if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
133 {
134 puts (s: "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 (requested_time: &ts, remaining: &ts) != 0)
142 ;
143
144 puts (s: "calling pthread_cancel the second time");
145 if (pthread_cancel (th: th2) != 0)
146 {
147 puts (s: "2nd cancel failed");
148 return 1;
149 }
150
151 puts (s: "calling pthread_join the second time");
152 if (pthread_join (th: th2, thread_return: &res) != 0)
153 {
154 puts (s: "2nd join failed");
155 return 1;
156 }
157 if (res != PTHREAD_CANCELED)
158 {
159 puts (s: "2nd thread not canceled");
160 return 1;
161 }
162
163 if (pthread_barrier_destroy (barrier: &b) != 0)
164 {
165 puts (s: "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

source code of glibc/sysdeps/pthread/tst-cancel25.c