source: trunk/src/libctests/glibc/linuxthreads/tst-cancel4.c@ 2036

Last change on this file since 2036 was 2036, checked in by bird, 20 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 9.8 KB
Line 
1/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
19
20/* NOTE: this tests functionality beyond POSIX. POSIX does not allow
21 exit to be called more than once. */
22
23#include <errno.h>
24#include <limits.h>
25#include <pthread.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <unistd.h>
30#include <sys/poll.h>
31#include <sys/select.h>
32#include <sys/uio.h>
33#include <sys/wait.h>
34
35/* The following interfaces are defined to be cancellation points but
36 tests are not yet implemented:
37
38 accept() aio_suspend() clock_nanosleep()
39 close() connect() creat()
40 fcntl() fsync() getmsg()
41 getpmsg() lockf() mq_receive()
42 mq_send() mq_timedreceive() mq_timedsend()
43 msgrcv() msgsnd() msync()
44 open() pause()
45 pread() pthread_cond_timedwait()
46 pthread_cond_wait() pthread_join() pthread_testcancel()
47 putmsg() putpmsg() pwrite()
48 recv()
49 recvfrom() recvmsg()
50 sem_timedwait() sem_wait() send()
51 sendmsg() sendto() sigpause()
52 sigsuspend() sigtimedwait() sigwait()
53 sigwaitinfo() system()
54 tcdrain()
55
56 Since STREAMS are not supported in the standard Linux kernel there
57 is no need to test the STREAMS related functions.
58*/
59
60/* Pipe descriptors. */
61static int fds[2];
62
63/* Often used barrier for two threads. */
64static pthread_barrier_t b2;
65
66
67static void *
68tf_read (void *arg)
69{
70 int r = pthread_barrier_wait (&b2);
71 if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
72 {
73 printf ("%s: barrier_wait failed\n", __FUNCTION__);
74 exit (1);
75 }
76
77 char buf[100];
78 ssize_t s = read (fds[0], buf, sizeof (buf));
79
80 printf ("%s: read returns with %zd\n", __FUNCTION__, s);
81
82 exit (1);
83}
84
85
86static void *
87tf_readv (void *arg)
88{
89 int r = pthread_barrier_wait (&b2);
90 if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
91 {
92 printf ("%s: barrier_wait failed\n", __FUNCTION__);
93 exit (1);
94 }
95
96 char buf[100];
97 struct iovec iov[1] = { [0] = { .iov_base = buf, .iov_len = sizeof (buf) } };
98 ssize_t s = readv (fds[0], iov, 1);
99
100 printf ("%s: readv returns with %zd\n", __FUNCTION__, s);
101
102 exit (1);
103}
104
105
106static void *
107tf_write (void *arg)
108{
109 int r = pthread_barrier_wait (&b2);
110 if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
111 {
112 printf ("%s: barrier_wait failed\n", __FUNCTION__);
113 exit (1);
114 }
115
116 char buf[100000];
117 memset (buf, '\0', sizeof (buf));
118 ssize_t s = write (fds[1], buf, sizeof (buf));
119
120 printf ("%s: write returns with %zd\n", __FUNCTION__, s);
121
122 exit (1);
123}
124
125
126static void *
127tf_writev (void *arg)
128{
129 int r = pthread_barrier_wait (&b2);
130 if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
131 {
132 printf ("%s: barrier_wait failed\n", __FUNCTION__);
133 exit (1);
134 }
135
136 char buf[100000];
137 memset (buf, '\0', sizeof (buf));
138 struct iovec iov[1] = { [0] = { .iov_base = buf, .iov_len = sizeof (buf) } };
139 ssize_t s = writev (fds[1], iov, 1);
140
141 printf ("%s: writev returns with %zd\n", __FUNCTION__, s);
142
143 exit (1);
144}
145
146
147static void *
148tf_sleep (void *arg)
149{
150 int r = pthread_barrier_wait (&b2);
151 if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
152 {
153 printf ("%s: barrier_wait failed\n", __FUNCTION__);
154 exit (1);
155 }
156
157 sleep (1000000);
158
159 printf ("%s: sleep returns\n", __FUNCTION__);
160
161 exit (1);
162}
163
164
165static void *
166tf_usleep (void *arg)
167{
168 int r = pthread_barrier_wait (&b2);
169 if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
170 {
171 printf ("%s: barrier_wait failed\n", __FUNCTION__);
172 exit (1);
173 }
174
175 usleep ((useconds_t) ULONG_MAX);
176
177 printf ("%s: usleep returns\n", __FUNCTION__);
178
179 exit (1);
180}
181
182
183static void *
184tf_nanosleep (void *arg)
185{
186 int r = pthread_barrier_wait (&b2);
187 if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
188 {
189 printf ("%s: barrier_wait failed\n", __FUNCTION__);
190 exit (1);
191 }
192
193 struct timespec ts = { .tv_sec = 10000000, .tv_nsec = 0 };
194 while (nanosleep (&ts, &ts) != 0)
195 continue;
196
197 printf ("%s: nanosleep returns\n", __FUNCTION__);
198
199 exit (1);
200}
201
202
203static void *
204tf_select (void *arg)
205{
206 int r = pthread_barrier_wait (&b2);
207 if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
208 {
209 printf ("%s: barrier_wait failed\n", __FUNCTION__);
210 exit (1);
211 }
212
213 fd_set rfs;
214 FD_ZERO (&rfs);
215 FD_SET (fds[0], &rfs);
216
217 int s = select (fds[0] + 1, &rfs, NULL, NULL, NULL);
218
219 printf ("%s: select returns with %d (%s)\n", __FUNCTION__, s,
220 strerror (errno));
221
222 exit (1);
223}
224
225
226static void *
227tf_pselect (void *arg)
228{
229 int r = pthread_barrier_wait (&b2);
230 if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
231 {
232 printf ("%s: barrier_wait failed\n", __FUNCTION__);
233 exit (1);
234 }
235
236 fd_set rfs;
237 FD_ZERO (&rfs);
238 FD_SET (fds[0], &rfs);
239
240 int s = pselect (fds[0] + 1, &rfs, NULL, NULL, NULL, NULL);
241
242 printf ("%s: pselect returns with %d (%s)\n", __FUNCTION__, s,
243 strerror (errno));
244
245 exit (1);
246}
247
248
249static void *
250tf_poll (void *arg)
251{
252 int r = pthread_barrier_wait (&b2);
253 if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
254 {
255 printf ("%s: barrier_wait failed\n", __FUNCTION__);
256 exit (1);
257 }
258
259 struct pollfd rfs[1] = { [0] = { .fd = fds[0], .events = POLLIN } };
260
261 int s = poll (rfs, 1, -1);
262
263 printf ("%s: poll returns with %d (%s)\n", __FUNCTION__, s,
264 strerror (errno));
265
266 exit (1);
267}
268
269
270static void *
271tf_wait (void *arg)
272{
273 int r = pthread_barrier_wait (&b2);
274 if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
275 {
276 printf ("%s: barrier_wait failed\n", __FUNCTION__);
277 exit (1);
278 }
279
280 pid_t pid = fork ();
281 if (pid == -1)
282 {
283 puts ("fork failed");
284 exit (1);
285 }
286
287 if (pid == 0)
288 {
289 /* Make the program disappear after a while. */
290 sleep (10);
291 exit (0);
292 }
293
294 int s = wait (NULL);
295
296 printf ("%s: wait returns with %d (%s)\n", __FUNCTION__, s,
297 strerror (errno));
298
299 exit (1);
300}
301
302
303static void *
304tf_waitpid (void *arg)
305{
306 int r = pthread_barrier_wait (&b2);
307 if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
308 {
309 printf ("%s: barrier_wait failed\n", __FUNCTION__);
310 exit (1);
311 }
312
313 pid_t pid = fork ();
314 if (pid == -1)
315 {
316 puts ("fork failed");
317 exit (1);
318 }
319
320 if (pid == 0)
321 {
322 /* Make the program disappear after a while. */
323 sleep (10);
324 exit (0);
325 }
326
327 int s = waitpid (-1, NULL, 0);
328
329 printf ("%s: waitpid returns with %d (%s)\n", __FUNCTION__, s,
330 strerror (errno));
331
332 exit (1);
333}
334
335
336static void *
337tf_waitid (void *arg)
338{
339 int r = pthread_barrier_wait (&b2);
340 if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
341 {
342 printf ("%s: barrier_wait failed\n", __FUNCTION__);
343 exit (1);
344 }
345
346 pid_t pid = fork ();
347 if (pid == -1)
348 {
349 puts ("fork failed");
350 exit (1);
351 }
352
353 if (pid == 0)
354 {
355 /* Make the program disappear after a while. */
356 sleep (10);
357 exit (0);
358 }
359
360#ifndef WEXITED
361# define WEXITED 0
362#endif
363 siginfo_t si;
364 int s = waitid (P_PID, pid, &si, WEXITED);
365
366 printf ("%s: waitid returns with %d (%s)\n", __FUNCTION__, s,
367 strerror (errno));
368
369 exit (1);
370}
371
372
373static struct
374{
375 void *(*tf) (void *);
376 int nb;
377} tests[] =
378{
379 { tf_read, 2 },
380 { tf_readv, 2 },
381 { tf_select, 2 },
382 { tf_pselect, 2 },
383 { tf_poll, 2 },
384 { tf_write, 2 },
385 { tf_writev, 2},
386 { tf_sleep, 2 },
387 { tf_usleep, 2 },
388 { tf_nanosleep, 2 },
389 { tf_wait, 2 },
390 { tf_waitid, 2 },
391 { tf_waitpid, 2 },
392};
393#define ntest_tf (sizeof (tests) / sizeof (tests[0]))
394
395
396static int
397do_test (void)
398{
399 if (pipe (fds) != 0)
400 {
401 puts ("pipe failed");
402 exit (1);
403 }
404
405 int cnt;
406 for (cnt = 0; cnt < ntest_tf; ++cnt)
407 {
408 printf ("round %d\n", cnt);
409
410 if (pthread_barrier_init (&b2, NULL, tests[cnt].nb) != 0)
411 {
412 puts ("b2 init failed");
413 exit (1);
414 }
415
416 pthread_t th;
417 if (pthread_create (&th, NULL, tests[cnt].tf, NULL) != 0)
418 {
419 printf ("create for round %d test failed\n", cnt);
420 exit (1);
421 }
422
423 puts ("barrier waits");
424
425 int r = pthread_barrier_wait (&b2);
426 if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
427 {
428 printf ("%s: barrier_wait failed\n", __FUNCTION__);
429 exit (1);
430 }
431
432 puts ("nanosleep delay");
433
434 struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
435 while (nanosleep (&ts, &ts) != 0)
436 continue;
437
438 if (pthread_cancel (th) != 0)
439 {
440 printf ("cancel in round %d failed\n", cnt);
441 exit (1);
442 }
443
444 void *status;
445 if (pthread_join (th, &status) != 0)
446 {
447 printf ("join in round %d failed\n", cnt);
448 exit (1);
449 }
450 if (status != PTHREAD_CANCELED)
451 {
452 printf ("thread in round %d not canceled\n", cnt);
453 exit (1);
454 }
455 printf ("test %d successful\n", cnt);
456
457 if (pthread_barrier_destroy (&b2) != 0)
458 {
459 puts ("barrier_destroy failed");
460 exit (1);
461 }
462 }
463
464 return 0;
465}
466
467#define TIMEOUT 60
468#define TEST_FUNCTION do_test ()
469#include "../test-skeleton.c"
Note: See TracBrowser for help on using the repository browser.