(root)/
glibc-2.38/
sysdeps/
pthread/
tst-signal1.c
       1  /* Copyright (C) 2002-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 <pthread.h>
      20  #include <signal.h>
      21  #include <stdio.h>
      22  #include <stdlib.h>
      23  #include <string.h>
      24  #include <unistd.h>
      25  #include <sys/mman.h>
      26  #include <sys/wait.h>
      27  
      28  #include <support/xunistd.h>
      29  
      30  static sigset_t ss;
      31  static pthread_barrier_t *b;
      32  
      33  
      34  static void *
      35  tf (void *arg)
      36  {
      37    sigdelset (&ss, SIGINT);
      38  
      39    if (pthread_sigmask (SIG_SETMASK, &ss, NULL) != 0)
      40      {
      41        puts ("2nd pthread_sigmask failed");
      42        exit (1);
      43      }
      44  
      45    pthread_barrier_wait (b);
      46  
      47    int sig;
      48    int res = sigwait (&ss, &sig);
      49    if (res == 0)
      50      {
      51        printf ("sigwait returned successfully with signal %d\n", sig);
      52        exit (1);
      53      }
      54  
      55    printf ("sigwait returned with %s (%d)\n", strerror (res), res);
      56  
      57    return NULL;
      58  }
      59  
      60  
      61  static void
      62  receiver (void)
      63  {
      64    pthread_t th;
      65  
      66    /* Make sure the process doesn't run forever.  */
      67    alarm (10);
      68  
      69    sigfillset (&ss);
      70  
      71    if (pthread_sigmask (SIG_SETMASK, &ss, NULL) != 0)
      72      {
      73        puts ("1st pthread_sigmask failed");
      74        exit (1);
      75      }
      76  
      77    if (pthread_create (&th, NULL, tf, NULL) != 0)
      78      {
      79        puts ("pthread_create failed");
      80        exit (1);
      81      }
      82  
      83    if (pthread_join (th, NULL) == 0)
      84      {
      85        puts ("thread joined?!");
      86        exit (1);
      87      }
      88  
      89    _exit (0);
      90  }
      91  
      92  
      93  static int
      94  do_test (void)
      95  {
      96    char tmp[] = "/tmp/tst-signal1-XXXXXX";
      97  
      98    int fd = mkstemp (tmp);
      99    if (fd == -1)
     100      {
     101        puts ("mkstemp failed");
     102        exit (1);
     103      }
     104  
     105    unlink (tmp);
     106  
     107    int i;
     108    for (i = 0; i < 20; ++i)
     109      xwrite (fd, "foobar xyzzy", 12);
     110  
     111    b = mmap (NULL, sizeof (pthread_barrier_t), PROT_READ | PROT_WRITE,
     112  	    MAP_SHARED, fd, 0);
     113    if (b == MAP_FAILED)
     114      {
     115        puts ("mmap failed");
     116        exit (1);
     117      }
     118  
     119    pthread_barrierattr_t ba;
     120    if (pthread_barrierattr_init (&ba) != 0)
     121      {
     122        puts ("barrierattr_init failed");
     123        exit (1);
     124      }
     125  
     126    if (pthread_barrierattr_setpshared (&ba, PTHREAD_PROCESS_SHARED) != 0)
     127      {
     128        puts ("barrierattr_setpshared failed");
     129        exit (1);
     130      }
     131  
     132    if (pthread_barrier_init (b, &ba, 2) != 0)
     133      {
     134        puts ("barrier_init failed");
     135        exit (1);
     136      }
     137  
     138    if (pthread_barrierattr_destroy (&ba) != 0)
     139      {
     140        puts ("barrierattr_destroy failed");
     141        exit (1);
     142      }
     143  
     144    pid_t pid = fork ();
     145    if (pid == -1)
     146      {
     147        puts ("fork failed");
     148        exit (1);
     149      }
     150  
     151    if (pid == 0)
     152      receiver ();
     153  
     154    pthread_barrier_wait (b);
     155  
     156    /* Wait a bit more.  */
     157    struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 };
     158    nanosleep (&ts, NULL);
     159  
     160    /* Send the signal.  */
     161    puts ("sending the signal now");
     162    kill (pid, SIGINT);
     163  
     164    /* Wait for the process to terminate.  */
     165    int status;
     166    if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
     167      {
     168        puts ("wrong child reported terminated");
     169        exit (1);
     170      }
     171  
     172    if (!WIFSIGNALED (status))
     173      {
     174        puts ("child wasn't signalled");
     175        exit (1);
     176      }
     177  
     178    if (WTERMSIG (status) != SIGINT)
     179      {
     180        puts ("child not terminated with SIGINT");
     181        exit (1);
     182      }
     183  
     184    return 0;
     185  }
     186  
     187  #define TEST_FUNCTION do_test ()
     188  #include "../test-skeleton.c"