(root)/
glibc-2.38/
sysdeps/
pthread/
tst-cancel19.c
       1  /* Copyright (C) 2003-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <errno.h>
      19  #include <error.h>
      20  #include <fcntl.h>
      21  #include <pthread.h>
      22  #include <signal.h>
      23  #include <stdio.h>
      24  #include <stdlib.h>
      25  #include <string.h>
      26  #include <sys/select.h>
      27  #include <sys/time.h>
      28  #include <unistd.h>
      29  
      30  static void *
      31  tf (void *arg)
      32  {
      33    return NULL;
      34  }
      35  
      36  static void
      37  handler (int sig)
      38  {
      39  }
      40  
      41  static void __attribute__ ((noinline))
      42  clobber_lots_of_regs (void)
      43  {
      44  #define X1(n) long r##n = 10##n; __asm __volatile ("" : "+r" (r##n));
      45  #define X2(n) X1(n##0) X1(n##1) X1(n##2) X1(n##3) X1(n##4)
      46  #define X3(n) X2(n##0) X2(n##1) X2(n##2) X2(n##3) X2(n##4)
      47    X3(0) X3(1) X3(2) X3(3) X3(4)
      48  #undef X1
      49  #define X1(n) __asm __volatile ("" : : "r" (r##n));
      50    X3(0) X3(1) X3(2) X3(3) X3(4)
      51  #undef X1
      52  #undef X2
      53  #undef X3
      54  }
      55  
      56  static int
      57  do_test (void)
      58  {
      59    pthread_t th;
      60    int old, rc;
      61    int ret = 0;
      62    int fd[2];
      63  
      64    rc = pipe (fd);
      65    if (rc < 0)
      66      error (EXIT_FAILURE, errno, "couldn't create pipe");
      67  
      68    rc = pthread_create (&th, NULL, tf, NULL);
      69    if (rc)
      70      error (EXIT_FAILURE, rc, "couldn't create thread");
      71  
      72    rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
      73    if (rc)
      74      {
      75        error (0, rc, "1st pthread_setcanceltype failed");
      76        ret = 1;
      77      }
      78    if (old != PTHREAD_CANCEL_DEFERRED && old != PTHREAD_CANCEL_ASYNCHRONOUS)
      79      {
      80        error (0, 0, "1st pthread_setcanceltype returned invalid value %d",
      81  	     old);
      82        ret = 1;
      83      }
      84  
      85    clobber_lots_of_regs ();
      86    close (fd[0]);
      87  
      88    rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
      89    if (rc)
      90      {
      91        error (0, rc, "pthread_setcanceltype after close failed");
      92        ret = 1;
      93      }
      94    if (old != PTHREAD_CANCEL_DEFERRED)
      95      {
      96        error (0, 0, "pthread_setcanceltype after close returned invalid value %d",
      97  	     old);
      98        ret = 1;
      99      }
     100  
     101    clobber_lots_of_regs ();
     102    close (fd[1]);
     103  
     104    rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
     105    if (rc)
     106      {
     107        error (0, rc, "pthread_setcanceltype after 2nd close failed");
     108        ret = 1;
     109      }
     110    if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
     111      {
     112        error (0, 0, "pthread_setcanceltype after 2nd close returned invalid value %d",
     113  	     old);
     114        ret = 1;
     115      }
     116  
     117    struct sigaction sa = { .sa_handler = handler, .sa_flags = 0 };
     118    sigemptyset (&sa.sa_mask);
     119    sigaction (SIGALRM, &sa, NULL);
     120  
     121    struct itimerval it;
     122    it.it_value.tv_sec = 1;
     123    it.it_value.tv_usec = 0;
     124    it.it_interval = it.it_value;
     125    setitimer (ITIMER_REAL, &it, NULL);
     126  
     127    clobber_lots_of_regs ();
     128    pause ();
     129  
     130    memset (&it, 0, sizeof (it));
     131    setitimer (ITIMER_REAL, &it, NULL);
     132  
     133    rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
     134    if (rc)
     135      {
     136        error (0, rc, "pthread_setcanceltype after pause failed");
     137        ret = 1;
     138      }
     139    if (old != PTHREAD_CANCEL_DEFERRED)
     140      {
     141        error (0, 0, "pthread_setcanceltype after pause returned invalid value %d",
     142  	     old);
     143        ret = 1;
     144      }
     145  
     146    it.it_value.tv_sec = 1;
     147    it.it_value.tv_usec = 0;
     148    it.it_interval = it.it_value;
     149    setitimer (ITIMER_REAL, &it, NULL);
     150  
     151    clobber_lots_of_regs ();
     152    pause ();
     153  
     154    memset (&it, 0, sizeof (it));
     155    setitimer (ITIMER_REAL, &it, NULL);
     156  
     157    rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
     158    if (rc)
     159      {
     160        error (0, rc, "pthread_setcanceltype after 2nd pause failed");
     161        ret = 1;
     162      }
     163    if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
     164      {
     165        error (0, 0, "pthread_setcanceltype after 2nd pause returned invalid value %d",
     166  	     old);
     167        ret = 1;
     168      }
     169  
     170    char fname[] = "/tmp/tst-cancel19-dir-XXXXXX\0foo/bar";
     171    char *enddir = strchr (fname, '\0');
     172    if (mkdtemp (fname) == NULL)
     173      {
     174        error (0, errno, "mkdtemp failed");
     175        ret = 1;
     176      }
     177    *enddir = '/';
     178  
     179    clobber_lots_of_regs ();
     180    creat (fname, 0400);
     181  
     182    rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
     183    if (rc)
     184      {
     185        error (0, rc, "pthread_setcanceltype after creat failed");
     186        ret = 1;
     187      }
     188    if (old != PTHREAD_CANCEL_DEFERRED)
     189      {
     190        error (0, 0, "pthread_setcanceltype after creat returned invalid value %d",
     191  	     old);
     192        ret = 1;
     193      }
     194  
     195    clobber_lots_of_regs ();
     196    creat (fname, 0400);
     197  
     198    rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
     199    if (rc)
     200      {
     201        error (0, rc, "pthread_setcanceltype after 2nd creat failed");
     202        ret = 1;
     203      }
     204    if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
     205      {
     206        error (0, 0, "pthread_setcanceltype after 2nd creat returned invalid value %d",
     207  	     old);
     208        ret = 1;
     209      }
     210  
     211    clobber_lots_of_regs ();
     212    open (fname, O_CREAT, 0400);
     213  
     214    rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
     215    if (rc)
     216      {
     217        error (0, rc, "pthread_setcanceltype after open failed");
     218        ret = 1;
     219      }
     220    if (old != PTHREAD_CANCEL_DEFERRED)
     221      {
     222        error (0, 0, "pthread_setcanceltype after open returned invalid value %d",
     223  	     old);
     224        ret = 1;
     225      }
     226  
     227    clobber_lots_of_regs ();
     228    open (fname, O_CREAT, 0400);
     229  
     230    rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
     231    if (rc)
     232      {
     233        error (0, rc, "pthread_setcanceltype after 2nd open failed");
     234        ret = 1;
     235      }
     236    if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
     237      {
     238        error (0, 0, "pthread_setcanceltype after 2nd open returned invalid value %d",
     239  	     old);
     240        ret = 1;
     241      }
     242  
     243    *enddir = '\0';
     244    rmdir (fname);
     245  
     246    clobber_lots_of_regs ();
     247    select (-1, NULL, NULL, NULL, NULL);
     248  
     249    rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
     250    if (rc)
     251      {
     252        error (0, rc, "pthread_setcanceltype after select failed");
     253        ret = 1;
     254      }
     255    if (old != PTHREAD_CANCEL_DEFERRED)
     256      {
     257        error (0, 0, "pthread_setcanceltype after select returned invalid value %d",
     258  	     old);
     259        ret = 1;
     260      }
     261  
     262    clobber_lots_of_regs ();
     263    select (-1, NULL, NULL, NULL, NULL);
     264  
     265    rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
     266    if (rc)
     267      {
     268        error (0, rc, "pthread_setcanceltype after 2nd select failed");
     269        ret = 1;
     270      }
     271    if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
     272      {
     273        error (0, 0, "pthread_setcanceltype after 2nd select returned invalid value %d",
     274  	     old);
     275        ret = 1;
     276      }
     277  
     278    pthread_join (th, NULL);
     279  
     280    return ret;
     281  }
     282  
     283  #define TEST_FUNCTION do_test ()
     284  #include "../test-skeleton.c"