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