(root)/
glibc-2.38/
sysdeps/
pthread/
tst-cancel4-common.c
       1  /* Common file for all tst-cancel4_*
       2  
       3     Copyright (C) 2016-2023 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  
      20  static int
      21  do_test (void)
      22  {
      23    if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) != 0)
      24      {
      25        perror ("socketpair");
      26        exit (1);
      27      }
      28  
      29    set_socket_buffer (fds[1]);
      30  
      31    if (mktemp (fifoname) == NULL)
      32      {
      33        printf ("%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 (&b2, NULL, tests[cnt].nb) != 0)
      45  	{
      46  	  puts ("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 (&th, NULL, tests[cnt].tf, NULL) != 0)
      55  	{
      56  	  printf ("create for '%s' test failed\n", tests[cnt].name);
      57  	  result = 1;
      58  	  continue;
      59  	}
      60  
      61        int r = pthread_barrier_wait (&b2);
      62        if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
      63  	{
      64  	  printf ("%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 (&ts, &ts) != 0)
      71  	continue;
      72  
      73        if (pthread_cancel (th) != 0)
      74  	{
      75  	  printf ("cancel for '%s' failed\n", tests[cnt].name);
      76  	  result = 1;
      77  	  continue;
      78  	}
      79  
      80        void *status;
      81        if (pthread_join (th, &status) != 0)
      82  	{
      83  	  printf ("join for '%s' failed\n", tests[cnt].name);
      84  	  result = 1;
      85  	  continue;
      86  	}
      87        if (status != PTHREAD_CANCELED)
      88  	{
      89  	  printf ("thread for '%s' not canceled\n", tests[cnt].name);
      90  	  result = 1;
      91  	  continue;
      92  	}
      93  
      94        if (pthread_barrier_destroy (&b2) != 0)
      95  	{
      96  	  puts ("barrier_destroy failed");
      97  	  result = 1;
      98  	  continue;
      99  	}
     100  
     101        if (cl_called == 0)
     102  	{
     103  	  printf ("cleanup handler not called for '%s'\n", tests[cnt].name);
     104  	  result = 1;
     105  	  continue;
     106  	}
     107        if (cl_called > 1)
     108  	{
     109  	  printf ("cleanup handler called more than once for '%s'\n",
     110  		  tests[cnt].name);
     111  	  result = 1;
     112  	  continue;
     113  	}
     114  
     115        printf ("in-time cancel test of '%s' successful\n", tests[cnt].name);
     116  
     117        if (tempfd != -1)
     118  	{
     119  	  close (tempfd);
     120  	  tempfd = -1;
     121  	}
     122        if (tempfd2 != -1)
     123  	{
     124  	  close (tempfd2);
     125  	  tempfd2 = -1;
     126  	}
     127        if (tempfname != NULL)
     128  	{
     129  	  unlink (tempfname);
     130  	  free (tempfname);
     131  	  tempfname = NULL;
     132  	}
     133        if (tempmsg != -1)
     134  	{
     135  	  msgctl (tempmsg, IPC_RMID, NULL);
     136  	  tempmsg = -1;
     137  	}
     138      }
     139  
     140    for (cnt = 0; cnt < ntest_tf; ++cnt)
     141      {
     142        if (pthread_barrier_init (&b2, NULL, tests[cnt].nb) != 0)
     143  	{
     144  	  puts ("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 (&th, NULL, tests[cnt].tf, (void *) 1l) != 0)
     153  	{
     154  	  printf ("create for '%s' test failed\n", tests[cnt].name);
     155  	  result = 1;
     156  	  continue;
     157  	}
     158  
     159        int r = pthread_barrier_wait (&b2);
     160        if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
     161  	{
     162  	  printf ("%s: barrier_wait failed\n", __func__);
     163  	  result = 1;
     164  	  continue;
     165  	}
     166  
     167        if (pthread_cancel (th) != 0)
     168  	{
     169  	  printf ("cancel for '%s' failed\n", tests[cnt].name);
     170  	  result = 1;
     171  	  continue;
     172  	}
     173  
     174        r = pthread_barrier_wait (&b2);
     175        if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
     176  	{
     177  	  printf ("%s: barrier_wait failed\n", __func__);
     178  	  result = 1;
     179  	  continue;
     180  	}
     181  
     182        void *status;
     183        if (pthread_join (th, &status) != 0)
     184  	{
     185  	  printf ("join for '%s' failed\n", tests[cnt].name);
     186  	  result = 1;
     187  	  continue;
     188  	}
     189        if (status != PTHREAD_CANCELED)
     190  	{
     191  	  printf ("thread for '%s' not canceled\n", tests[cnt].name);
     192  	  result = 1;
     193  	  continue;
     194  	}
     195  
     196        if (pthread_barrier_destroy (&b2) != 0)
     197  	{
     198  	  puts ("barrier_destroy failed");
     199  	  result = 1;
     200  	  continue;
     201  	}
     202  
     203        if (cl_called == 0)
     204  	{
     205  	  printf ("cleanup handler not called for '%s'\n", tests[cnt].name);
     206  	  result = 1;
     207  	  continue;
     208  	}
     209        if (cl_called > 1)
     210  	{
     211  	  printf ("cleanup handler called more than once for '%s'\n",
     212  		  tests[cnt].name);
     213  	  result = 1;
     214  	  continue;
     215  	}
     216  
     217        printf ("early cancel test of '%s' successful\n", tests[cnt].name);
     218  
     219        if (tempfd != -1)
     220  	{
     221  	  close (tempfd);
     222  	  tempfd = -1;
     223  	}
     224        if (tempfd2 != -1)
     225  	{
     226  	  close (tempfd2);
     227  	  tempfd2 = -1;
     228  	}
     229        if (tempfname != NULL)
     230  	{
     231  	  unlink (tempfname);
     232  	  free (tempfname);
     233  	  tempfname = NULL;
     234  	}
     235        if (tempmsg != -1)
     236  	{
     237  	  msgctl (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>