1/* Common file for all tst-cancel4_*
2
3 Copyright (C) 2016-2022 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <https://www.gnu.org/licenses/>. */
19
20static int
21do_test (void)
22{
23 if (socketpair (AF_UNIX, SOCK_STREAM, protocol: 0, fds: fds) != 0)
24 {
25 perror ("socketpair");
26 exit (1);
27 }
28
29 set_socket_buffer (fds[1]);
30
31 if (mktemp (template: fifoname) == NULL)
32 {
33 printf (format: "%s: cannot generate temp file name: %m\n", __func__);
34 exit (1);
35 }
36
37 int result = 0;
38 size_t cnt;
39 for (cnt = 0; cnt < ntest_tf; ++cnt)
40 {
41 if (tests[cnt].only_early)
42 continue;
43
44 if (pthread_barrier_init (barrier: &b2, NULL, count: tests[cnt].nb) != 0)
45 {
46 puts (s: "b2 init failed");
47 exit (1);
48 }
49
50 /* Reset the counter for the cleanup handler. */
51 cl_called = 0;
52
53 pthread_t th;
54 if (pthread_create (newthread: &th, NULL, start_routine: tests[cnt].tf, NULL) != 0)
55 {
56 printf (format: "create for '%s' test failed\n", tests[cnt].name);
57 result = 1;
58 continue;
59 }
60
61 int r = pthread_barrier_wait (barrier: &b2);
62 if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
63 {
64 printf (format: "%s: barrier_wait failed\n", __func__);
65 result = 1;
66 continue;
67 }
68
69 struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
70 while (nanosleep (requested_time: &ts, remaining: &ts) != 0)
71 continue;
72
73 if (pthread_cancel (th: th) != 0)
74 {
75 printf (format: "cancel for '%s' failed\n", tests[cnt].name);
76 result = 1;
77 continue;
78 }
79
80 void *status;
81 if (pthread_join (th: th, thread_return: &status) != 0)
82 {
83 printf (format: "join for '%s' failed\n", tests[cnt].name);
84 result = 1;
85 continue;
86 }
87 if (status != PTHREAD_CANCELED)
88 {
89 printf (format: "thread for '%s' not canceled\n", tests[cnt].name);
90 result = 1;
91 continue;
92 }
93
94 if (pthread_barrier_destroy (barrier: &b2) != 0)
95 {
96 puts (s: "barrier_destroy failed");
97 result = 1;
98 continue;
99 }
100
101 if (cl_called == 0)
102 {
103 printf (format: "cleanup handler not called for '%s'\n", tests[cnt].name);
104 result = 1;
105 continue;
106 }
107 if (cl_called > 1)
108 {
109 printf (format: "cleanup handler called more than once for '%s'\n",
110 tests[cnt].name);
111 result = 1;
112 continue;
113 }
114
115 printf (format: "in-time cancel test of '%s' successful\n", tests[cnt].name);
116
117 if (tempfd != -1)
118 {
119 close (fd: tempfd);
120 tempfd = -1;
121 }
122 if (tempfd2 != -1)
123 {
124 close (fd: tempfd2);
125 tempfd2 = -1;
126 }
127 if (tempfname != NULL)
128 {
129 unlink (name: tempfname);
130 free (ptr: tempfname);
131 tempfname = NULL;
132 }
133 if (tempmsg != -1)
134 {
135 msgctl (msqid: tempmsg, IPC_RMID, NULL);
136 tempmsg = -1;
137 }
138 }
139
140 for (cnt = 0; cnt < ntest_tf; ++cnt)
141 {
142 if (pthread_barrier_init (barrier: &b2, NULL, count: tests[cnt].nb) != 0)
143 {
144 puts (s: "b2 init failed");
145 exit (1);
146 }
147
148 /* Reset the counter for the cleanup handler. */
149 cl_called = 0;
150
151 pthread_t th;
152 if (pthread_create (newthread: &th, NULL, start_routine: tests[cnt].tf, arg: (void *) 1l) != 0)
153 {
154 printf (format: "create for '%s' test failed\n", tests[cnt].name);
155 result = 1;
156 continue;
157 }
158
159 int r = pthread_barrier_wait (barrier: &b2);
160 if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
161 {
162 printf (format: "%s: barrier_wait failed\n", __func__);
163 result = 1;
164 continue;
165 }
166
167 if (pthread_cancel (th: th) != 0)
168 {
169 printf (format: "cancel for '%s' failed\n", tests[cnt].name);
170 result = 1;
171 continue;
172 }
173
174 r = pthread_barrier_wait (barrier: &b2);
175 if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
176 {
177 printf (format: "%s: barrier_wait failed\n", __func__);
178 result = 1;
179 continue;
180 }
181
182 void *status;
183 if (pthread_join (th: th, thread_return: &status) != 0)
184 {
185 printf (format: "join for '%s' failed\n", tests[cnt].name);
186 result = 1;
187 continue;
188 }
189 if (status != PTHREAD_CANCELED)
190 {
191 printf (format: "thread for '%s' not canceled\n", tests[cnt].name);
192 result = 1;
193 continue;
194 }
195
196 if (pthread_barrier_destroy (barrier: &b2) != 0)
197 {
198 puts (s: "barrier_destroy failed");
199 result = 1;
200 continue;
201 }
202
203 if (cl_called == 0)
204 {
205 printf (format: "cleanup handler not called for '%s'\n", tests[cnt].name);
206 result = 1;
207 continue;
208 }
209 if (cl_called > 1)
210 {
211 printf (format: "cleanup handler called more than once for '%s'\n",
212 tests[cnt].name);
213 result = 1;
214 continue;
215 }
216
217 printf (format: "early cancel test of '%s' successful\n", tests[cnt].name);
218
219 if (tempfd != -1)
220 {
221 close (fd: tempfd);
222 tempfd = -1;
223 }
224 if (tempfd2 != -1)
225 {
226 close (fd: tempfd2);
227 tempfd2 = -1;
228 }
229 if (tempfname != NULL)
230 {
231 unlink (name: tempfname);
232 free (ptr: tempfname);
233 tempfname = NULL;
234 }
235 if (tempmsg != -1)
236 {
237 msgctl (msqid: tempmsg, IPC_RMID, NULL);
238 tempmsg = -1;
239 }
240 }
241
242 return result;
243}
244
245#define TIMEOUT 60
246#include <support/test-driver.c>
247

source code of glibc/sysdeps/pthread/tst-cancel4-common.c