Initial revision
[kopensolaris-gnu/glibc.git] / nptl / tst-cancel4.c
1 /* Copyright (C) 2002 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.  */
61 static int fds[2];
62
63 /* Often used barrier for two threads.  */
64 static pthread_barrier_t b2;
65
66
67 static void *
68 tf_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
86 static void *
87 tf_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
106 static void *
107 tf_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[10000];
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
126 static void *
127 tf_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[10000];
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
147 static void *
148 tf_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 (10000000);
158
159   printf ("%s: sleep returns\n", __FUNCTION__);
160
161   exit (1);
162 }
163
164
165 static void *
166 tf_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 (ULONG_MAX);
176
177   printf ("%s: usleep returns\n", __FUNCTION__);
178
179   exit (1);
180 }
181
182
183 static void *
184 tf_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
203 static void *
204 tf_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
226 static void *
227 tf_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
249 static void *
250 tf_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
270 static void *
271 tf_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
303 static void *
304 tf_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
336 static void *
337 tf_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   siginfo_t si;
361   int s = waitid (P_PID, pid, &si, 0);
362
363   printf ("%s: waitid returns with %d (%s)\n", __FUNCTION__, s,
364           strerror (errno));
365
366   exit (1);
367 }
368
369
370 static struct
371 {
372   void *(*tf) (void *);
373   int nb;
374 } tests[] =
375 {
376   { tf_read, 2 },
377   { tf_readv, 2 },
378   { tf_select, 2 },
379   { tf_pselect, 2 },
380   { tf_poll, 2 },
381   { tf_write, 2 },
382   { tf_writev, 2},
383   { tf_sleep, 2 },
384   { tf_usleep, 2 },
385   { tf_nanosleep, 2 },
386   { tf_wait, 2 },
387   { tf_waitid, 2 },
388   { tf_waitpid, 2 },
389 };
390 #define ntest_tf (sizeof (tests) / sizeof (tests[0]))
391
392
393 static int
394 do_test (void)
395 {
396   if (pipe (fds) != 0)
397     {
398       puts ("pipe failed");
399       exit (1);
400     }
401
402   int cnt;
403   for (cnt = 0; cnt < ntest_tf; ++cnt)
404     {
405       if (pthread_barrier_init (&b2, NULL, tests[cnt].nb) != 0)
406         {
407           puts ("b2 init failed");
408           exit (1);
409         }
410
411       /* read(2) test.  */
412       pthread_t th;
413       if (pthread_create (&th, NULL, tests[cnt].tf, NULL) != 0)
414         {
415           printf ("create for round %d test failed\n", cnt);
416           exit (1);
417         }
418
419       int r = pthread_barrier_wait (&b2);
420       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
421         {
422           printf ("%s: barrier_wait failed\n", __FUNCTION__);
423           exit (1);
424         }
425
426       struct timespec  ts = { .tv_sec = 0, .tv_nsec = 100000000 };
427       while (nanosleep (&ts, &ts) != 0)
428         continue;
429
430       if (pthread_cancel (th) != 0)
431         {
432           printf ("cancel in round %d failed\n", cnt);
433           exit (1);
434         }
435
436       void *status;
437       if (pthread_join (th, &status) != 0)
438         {
439           printf ("join in round %d failed\n", cnt);
440           exit (1);
441         }
442       if (status != PTHREAD_CANCELED)
443         {
444           printf ("thread in round %d not canceled\n", cnt);
445           exit (1);
446         }
447       printf ("test %d successful\n", cnt);
448
449       if (pthread_barrier_destroy (&b2) != 0)
450         {
451           puts ("barrier_destroy failed");
452           exit (1);
453         }
454     }
455
456   return 0;
457 }
458
459 #define TIMEOUT 60
460 #define TEST_FUNCTION do_test ()
461 #include "../test-skeleton.c"