(root)/
glibc-2.38/
sysdeps/
pthread/
tst-signal6.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 <pthread.h>
      19  #include <signal.h>
      20  #include <stdint.h>
      21  #include <stdio.h>
      22  #include <stdlib.h>
      23  #include <unistd.h>
      24  
      25  
      26  #ifdef SIGRTMIN
      27  
      28  # define N 2
      29  static pthread_barrier_t bar;
      30  static struct
      31  {
      32    void *p;
      33    pthread_t s;
      34  } ti[N];
      35  static int sig1;
      36  
      37  
      38  static void
      39  handler (int sig)
      40  {
      41    pthread_t self = pthread_self ();
      42    size_t i;
      43  
      44    for (i = 0; i < N; ++i)
      45      if (ti[i].s == self)
      46        {
      47  	if ((uintptr_t) ti[i].p <= (uintptr_t) &self
      48  	    && (uintptr_t) ti[i].p + 2 * MINSIGSTKSZ > (uintptr_t) &self)
      49  	  {
      50  	    puts ("alt stack not used");
      51  	    exit (1);
      52  	  }
      53  
      54  	printf ("thread %zu used alt stack for signal %d\n", i, sig);
      55  
      56  	return;
      57        }
      58  
      59    puts ("handler: thread not found");
      60    exit (1);
      61  }
      62  
      63  
      64  static void *
      65  tf (void *arg)
      66  {
      67    size_t nr = (uintptr_t) arg;
      68    if (nr >= N)
      69      {
      70        puts ("wrong nr parameter");
      71        exit (1);
      72      }
      73  
      74    sigset_t ss;
      75    sigemptyset (&ss);
      76    size_t i;
      77    for (i = 0; i < N; ++i)
      78      if (i != nr)
      79        if (sigaddset (&ss, sig1 + i) != 0)
      80  	{
      81  	  puts ("tf: sigaddset failed");
      82  	  exit (1);
      83  	}
      84    if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
      85      {
      86        puts ("tf: sigmask failed");
      87        exit (1);
      88      }
      89  
      90    void *p = malloc (2 * MINSIGSTKSZ);
      91    if (p == NULL)
      92      {
      93        puts ("tf: malloc failed");
      94        exit (1);
      95      }
      96  
      97    stack_t s;
      98    s.ss_sp = p;
      99    s.ss_size = 2 * MINSIGSTKSZ;
     100    s.ss_flags = 0;
     101    if (sigaltstack (&s, NULL) != 0)
     102      {
     103        puts ("tf: sigaltstack failed");
     104        exit (1);
     105      }
     106  
     107    ti[nr].p = p;
     108    ti[nr].s = pthread_self ();
     109  
     110    pthread_barrier_wait (&bar);
     111  
     112    pthread_barrier_wait (&bar);
     113  
     114    return NULL;
     115  }
     116  
     117  
     118  static int
     119  do_test (void)
     120  {
     121    sig1 = SIGRTMIN;
     122    if (sig1 + N > SIGRTMAX)
     123      {
     124        puts ("too few RT signals");
     125        return 0;
     126      }
     127  
     128    struct sigaction sa;
     129    sa.sa_handler = handler;
     130    sa.sa_flags = 0;
     131    sigemptyset (&sa.sa_mask);
     132  
     133    if (sigaction (sig1, &sa, NULL) != 0
     134        || sigaction (sig1 + 1, &sa, NULL) != 0
     135        || sigaction (sig1 + 2, &sa, NULL) != 0)
     136      {
     137        puts ("sigaction failed");
     138        return 1;
     139      }
     140  
     141    if (pthread_barrier_init (&bar, NULL, 1 + N) != 0)
     142      {
     143        puts ("barrier_init failed");
     144        return 1;
     145      }
     146  
     147    pthread_t th[N];
     148    size_t i;
     149    for (i = 0; i < N; ++i)
     150      if (pthread_create (&th[i], NULL, tf, (void *) (long int) i) != 0)
     151        {
     152  	puts ("create failed");
     153  	return 1;
     154        }
     155  
     156    /* Block the three signals.  */
     157    sigset_t ss;
     158    sigemptyset (&ss);
     159    for (i = 0; i <= N; ++i)
     160      sigaddset (&ss, sig1 + i);
     161    if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
     162      {
     163        puts ("main: sigmask failed");
     164        return 1;
     165      }
     166  
     167    pthread_barrier_wait (&bar);
     168  
     169    /* Send some signals.  */
     170    pid_t me = getpid ();
     171    kill (me, sig1 + N);
     172    for (i = 0; i < N; ++i)
     173      kill (me, sig1 + i);
     174    kill (me, sig1 + N);
     175  
     176    /* Give the signals a chance to be worked on.  */
     177    sleep (1);
     178  
     179    pthread_barrier_wait (&bar);
     180  
     181    for (i = 0; i < N; ++i)
     182      if (pthread_join (th[i], NULL) != 0)
     183        {
     184  	puts ("join failed");
     185  	return 1;
     186        }
     187  
     188    return 0;
     189  }
     190  
     191  # define TEST_FUNCTION do_test ()
     192  
     193  #else
     194  # define TEST_FUNCTION 0
     195  #endif
     196  #include "../test-skeleton.c"