Back to index

glibc  2.9
tst-cancel4.c
Go to the documentation of this file.
00001 /* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 /* NOTE: this tests functionality beyond POSIX.  POSIX does not allow
00021    exit to be called more than once.  */
00022 
00023 #include <errno.h>
00024 #include <limits.h>
00025 #include <pthread.h>
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <unistd.h>
00030 #include <sys/poll.h>
00031 #include <sys/select.h>
00032 #include <sys/uio.h>
00033 #include <sys/wait.h>
00034 
00035 /* The following interfaces are defined to be cancellation points but
00036    tests are not yet implemented:
00037 
00038      accept()              aio_suspend()      clock_nanosleep()
00039      close()               connect()          creat()
00040      fcntl()               fsync()            getmsg()
00041      getpmsg()             lockf()            mq_receive()
00042      mq_send()             mq_timedreceive()  mq_timedsend()
00043      msgrcv()              msgsnd()           msync()
00044                            open()             pause()
00045                            pread()            pthread_cond_timedwait()
00046      pthread_cond_wait()   pthread_join()     pthread_testcancel()
00047      putmsg()              putpmsg()          pwrite()
00048                                               recv()
00049      recvfrom()            recvmsg()
00050      sem_timedwait()       sem_wait()         send()
00051      sendmsg()             sendto()           sigpause()
00052      sigsuspend()          sigtimedwait()     sigwait()
00053      sigwaitinfo()                            system()
00054      tcdrain()
00055 
00056    Since STREAMS are not supported in the standard Linux kernel there
00057    is no need to test the STREAMS related functions.
00058 */
00059 
00060 /* Pipe descriptors.  */
00061 static int fds[2];
00062 
00063 /* Often used barrier for two threads.  */
00064 static pthread_barrier_t b2;
00065 
00066 
00067 static void *
00068 tf_read  (void *arg)
00069 {
00070   int r = pthread_barrier_wait (&b2);
00071   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
00072     {
00073       printf ("%s: barrier_wait failed\n", __FUNCTION__);
00074       exit (1);
00075     }
00076 
00077   char buf[100];
00078   ssize_t s = read (fds[0], buf, sizeof (buf));
00079 
00080   printf ("%s: read returns with %zd\n", __FUNCTION__, s);
00081 
00082   exit (1);
00083 }
00084 
00085 
00086 static void *
00087 tf_readv  (void *arg)
00088 {
00089   int r = pthread_barrier_wait (&b2);
00090   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
00091     {
00092       printf ("%s: barrier_wait failed\n", __FUNCTION__);
00093       exit (1);
00094     }
00095 
00096   char buf[100];
00097   struct iovec iov[1] = { [0] = { .iov_base = buf, .iov_len = sizeof (buf) } };
00098   ssize_t s = readv (fds[0], iov, 1);
00099 
00100   printf ("%s: readv returns with %zd\n", __FUNCTION__, s);
00101 
00102   exit (1);
00103 }
00104 
00105 
00106 static void *
00107 tf_write  (void *arg)
00108 {
00109   int r = pthread_barrier_wait (&b2);
00110   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
00111     {
00112       printf ("%s: barrier_wait failed\n", __FUNCTION__);
00113       exit (1);
00114     }
00115 
00116   char buf[100000];
00117   memset (buf, '\0', sizeof (buf));
00118   ssize_t s = write (fds[1], buf, sizeof (buf));
00119 
00120   printf ("%s: write returns with %zd\n", __FUNCTION__, s);
00121 
00122   exit (1);
00123 }
00124 
00125 
00126 static void *
00127 tf_writev  (void *arg)
00128 {
00129   int r = pthread_barrier_wait (&b2);
00130   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
00131     {
00132       printf ("%s: barrier_wait failed\n", __FUNCTION__);
00133       exit (1);
00134     }
00135 
00136   char buf[100000];
00137   memset (buf, '\0', sizeof (buf));
00138   struct iovec iov[1] = { [0] = { .iov_base = buf, .iov_len = sizeof (buf) } };
00139   ssize_t s = writev (fds[1], iov, 1);
00140 
00141   printf ("%s: writev returns with %zd\n", __FUNCTION__, s);
00142 
00143   exit (1);
00144 }
00145 
00146 
00147 static void *
00148 tf_sleep (void *arg)
00149 {
00150   int r = pthread_barrier_wait (&b2);
00151   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
00152     {
00153       printf ("%s: barrier_wait failed\n", __FUNCTION__);
00154       exit (1);
00155     }
00156 
00157   sleep (1000000);
00158 
00159   printf ("%s: sleep returns\n", __FUNCTION__);
00160 
00161   exit (1);
00162 }
00163 
00164 
00165 static void *
00166 tf_usleep (void *arg)
00167 {
00168   int r = pthread_barrier_wait (&b2);
00169   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
00170     {
00171       printf ("%s: barrier_wait failed\n", __FUNCTION__);
00172       exit (1);
00173     }
00174 
00175   usleep ((useconds_t) ULONG_MAX);
00176 
00177   printf ("%s: usleep returns\n", __FUNCTION__);
00178 
00179   exit (1);
00180 }
00181 
00182 
00183 static void *
00184 tf_nanosleep (void *arg)
00185 {
00186   int r = pthread_barrier_wait (&b2);
00187   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
00188     {
00189       printf ("%s: barrier_wait failed\n", __FUNCTION__);
00190       exit (1);
00191     }
00192 
00193   struct timespec ts = { .tv_sec = 10000000, .tv_nsec = 0 };
00194   while (nanosleep (&ts, &ts) != 0)
00195     continue;
00196 
00197   printf ("%s: nanosleep returns\n", __FUNCTION__);
00198 
00199   exit (1);
00200 }
00201 
00202 
00203 static void *
00204 tf_select (void *arg)
00205 {
00206   int r = pthread_barrier_wait (&b2);
00207   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
00208     {
00209       printf ("%s: barrier_wait failed\n", __FUNCTION__);
00210       exit (1);
00211     }
00212 
00213   fd_set rfs;
00214   FD_ZERO (&rfs);
00215   FD_SET (fds[0], &rfs);
00216 
00217   int s = select (fds[0] + 1, &rfs, NULL, NULL, NULL);
00218 
00219   printf ("%s: select returns with %d (%s)\n", __FUNCTION__, s,
00220          strerror (errno));
00221 
00222   exit (1);
00223 }
00224 
00225 
00226 static void *
00227 tf_pselect (void *arg)
00228 {
00229   int r = pthread_barrier_wait (&b2);
00230   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
00231     {
00232       printf ("%s: barrier_wait failed\n", __FUNCTION__);
00233       exit (1);
00234     }
00235 
00236   fd_set rfs;
00237   FD_ZERO (&rfs);
00238   FD_SET (fds[0], &rfs);
00239 
00240   int s = pselect (fds[0] + 1, &rfs, NULL, NULL, NULL, NULL);
00241 
00242   printf ("%s: pselect returns with %d (%s)\n", __FUNCTION__, s,
00243          strerror (errno));
00244 
00245   exit (1);
00246 }
00247 
00248 
00249 static void *
00250 tf_poll (void *arg)
00251 {
00252   int r = pthread_barrier_wait (&b2);
00253   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
00254     {
00255       printf ("%s: barrier_wait failed\n", __FUNCTION__);
00256       exit (1);
00257     }
00258 
00259   struct pollfd rfs[1] = { [0] = { .fd = fds[0], .events = POLLIN } };
00260 
00261   int s = poll (rfs, 1, -1);
00262 
00263   printf ("%s: poll returns with %d (%s)\n", __FUNCTION__, s,
00264          strerror (errno));
00265 
00266   exit (1);
00267 }
00268 
00269 
00270 static void *
00271 tf_wait (void *arg)
00272 {
00273   int r = pthread_barrier_wait (&b2);
00274   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
00275     {
00276       printf ("%s: barrier_wait failed\n", __FUNCTION__);
00277       exit (1);
00278     }
00279 
00280   pid_t pid = fork ();
00281   if (pid == -1)
00282     {
00283       puts ("fork failed");
00284       exit (1);
00285     }
00286 
00287   if (pid == 0)
00288     {
00289       /* Make the program disappear after a while.  */
00290       sleep (10);
00291       exit (0);
00292     }
00293 
00294   int s = wait (NULL);
00295 
00296   printf ("%s: wait returns with %d (%s)\n", __FUNCTION__, s,
00297          strerror (errno));
00298 
00299   exit (1);
00300 }
00301 
00302 
00303 static void *
00304 tf_waitpid (void *arg)
00305 {
00306   int r = pthread_barrier_wait (&b2);
00307   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
00308     {
00309       printf ("%s: barrier_wait failed\n", __FUNCTION__);
00310       exit (1);
00311     }
00312 
00313   pid_t pid = fork ();
00314   if (pid == -1)
00315     {
00316       puts ("fork failed");
00317       exit (1);
00318     }
00319 
00320   if (pid == 0)
00321     {
00322       /* Make the program disappear after a while.  */
00323       sleep (10);
00324       exit (0);
00325     }
00326 
00327   int s = waitpid (-1, NULL, 0);
00328 
00329   printf ("%s: waitpid returns with %d (%s)\n", __FUNCTION__, s,
00330          strerror (errno));
00331 
00332   exit (1);
00333 }
00334 
00335 
00336 static void *
00337 tf_waitid (void *arg)
00338 {
00339   int r = pthread_barrier_wait (&b2);
00340   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
00341     {
00342       printf ("%s: barrier_wait failed\n", __FUNCTION__);
00343       exit (1);
00344     }
00345 
00346   pid_t pid = fork ();
00347   if (pid == -1)
00348     {
00349       puts ("fork failed");
00350       exit (1);
00351     }
00352 
00353   if (pid == 0)
00354     {
00355       /* Make the program disappear after a while.  */
00356       sleep (10);
00357       exit (0);
00358     }
00359 
00360 #ifndef WEXITED
00361 # define WEXITED 0
00362 #endif
00363   siginfo_t si;
00364   int s = waitid (P_PID, pid, &si, WEXITED);
00365 
00366   printf ("%s: waitid returns with %d (%s)\n", __FUNCTION__, s,
00367          strerror (errno));
00368 
00369   exit (1);
00370 }
00371 
00372 
00373 static struct
00374 {
00375   void *(*tf) (void *);
00376   int nb;
00377 } tests[] =
00378 {
00379   { tf_read, 2 },
00380   { tf_readv, 2 },
00381   { tf_select, 2 },
00382   { tf_pselect, 2 },
00383   { tf_poll, 2 },
00384   { tf_write, 2 },
00385   { tf_writev, 2},
00386   { tf_sleep, 2 },
00387   { tf_usleep, 2 },
00388   { tf_nanosleep, 2 },
00389   { tf_wait, 2 },
00390   { tf_waitid, 2 },
00391   { tf_waitpid, 2 },
00392 };
00393 #define ntest_tf (sizeof (tests) / sizeof (tests[0]))
00394 
00395 
00396 static int
00397 do_test (void)
00398 {
00399   if (pipe (fds) != 0)
00400     {
00401       puts ("pipe failed");
00402       exit (1);
00403     }
00404 
00405   int cnt;
00406   for (cnt = 0; cnt < ntest_tf; ++cnt)
00407     {
00408       printf ("round %d\n", cnt);
00409 
00410       if (pthread_barrier_init (&b2, NULL, tests[cnt].nb) != 0)
00411        {
00412          puts ("b2 init failed");
00413          exit (1);
00414        }
00415 
00416       pthread_t th;
00417       if (pthread_create (&th, NULL, tests[cnt].tf, NULL) != 0)
00418        {
00419          printf ("create for round %d test failed\n", cnt);
00420          exit (1);
00421        }
00422 
00423       puts ("barrier waits");
00424 
00425       int r = pthread_barrier_wait (&b2);
00426       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
00427        {
00428          printf ("%s: barrier_wait failed\n", __FUNCTION__);
00429          exit (1);
00430        }
00431 
00432       puts ("nanosleep delay");
00433 
00434       struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
00435       while (nanosleep (&ts, &ts) != 0)
00436        continue;
00437 
00438       if (pthread_cancel (th) != 0)
00439        {
00440          printf ("cancel in round %d failed\n", cnt);
00441          exit (1);
00442        }
00443 
00444       void *status;
00445       if (pthread_join (th, &status) != 0)
00446        {
00447          printf ("join in round %d failed\n", cnt);
00448          exit (1);
00449        }
00450       if (status != PTHREAD_CANCELED)
00451        {
00452          printf ("thread in round %d not canceled\n", cnt);
00453          exit (1);
00454        }
00455       printf ("test %d successful\n", cnt);
00456 
00457       if (pthread_barrier_destroy (&b2) != 0)
00458        {
00459          puts ("barrier_destroy failed");
00460          exit (1);
00461        }
00462     }
00463 
00464   return 0;
00465 }
00466 
00467 #define TIMEOUT 60
00468 #define TEST_FUNCTION do_test ()
00469 #include "../test-skeleton.c"