(root)/
glibc-2.38/
nptl/
tst-pthread-attr-sigmask.c
       1  /* Tests for pthread_attr_setsigmask_np, pthread_attr_getsigmask_np.
       2     Copyright (C) 2020-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  /* This thread uses different masked status for SIGUSR1, SIGUSR2,
      20     SIGHUP to determine if signal masks are applied to new threads as
      21     expected.  */
      22  
      23  #include <signal.h>
      24  #include <stdbool.h>
      25  #include <stddef.h>
      26  #include <stdio.h>
      27  #include <support/check.h>
      28  #include <support/xsignal.h>
      29  #include <support/xthread.h>
      30  #include <threads.h>
      31  
      32  typedef bool signals[_NSIG];
      33  
      34  static const char *
      35  masked_or_unmasked (bool masked)
      36  {
      37    if (masked)
      38      return "masked";
      39    else
      40      return "unmasked";
      41  }
      42  
      43  /* Report an error if ACTUAL_MASK does not match EXPECTED_MASK.
      44     CONTEXT is used in error messages.  */
      45  static void
      46  check_sigmask (const char *context, signals expected_mask,
      47                 const sigset_t *actual_mask)
      48  {
      49    for (int sig = 1; sig < _NSIG; ++sig)
      50      if (sigismember (actual_mask, sig) != expected_mask[sig])
      51        {
      52          support_record_failure ();
      53          printf ("error: %s: signal %d should be %s, but is %s\n",
      54                  context, sig,
      55                  masked_or_unmasked (sigismember (actual_mask, sig)),
      56                  masked_or_unmasked (expected_mask[sig]));
      57        }
      58  }
      59  
      60  /* Report an error if the current thread signal mask does not match
      61     EXPECTED_MASK.  CONTEXT is used in error messages.  */
      62  static void
      63  check_current_sigmask (const char *context, signals expected_mask)
      64  {
      65    sigset_t actual_mask;
      66    xpthread_sigmask (SIG_SETMASK, NULL, &actual_mask);
      67    check_sigmask (context, expected_mask, &actual_mask);
      68  }
      69  
      70  /* Thread start routine which checks the current thread signal mask
      71     against CLOSURE.  */
      72  static void *
      73  check_sigmask_thread_function (void *closure)
      74  {
      75    check_current_sigmask ("on thread", closure);
      76    return NULL;
      77  }
      78  
      79  /* Same for C11 threads.  */
      80  static int
      81  check_sigmask_thread_function_c11 (void *closure)
      82  {
      83    check_current_sigmask ("on C11 thread", closure);
      84    return 0;
      85  }
      86  
      87  /* Launch a POSIX thread with ATTR (which can be NULL) and check that
      88     it has the expected signal mask.  */
      89  static void
      90  check_posix_thread (pthread_attr_t *attr, signals expected_mask)
      91  {
      92    xpthread_join (xpthread_create (attr, check_sigmask_thread_function,
      93                                    expected_mask));
      94  }
      95  
      96  /* Launch a C11 thread and check that it has the expected signal
      97     mask.  */
      98  static void
      99  check_c11_thread (signals expected_mask)
     100  {
     101    thrd_t thr;
     102    TEST_VERIFY_EXIT (thrd_create (&thr, check_sigmask_thread_function_c11,
     103                                   expected_mask) == thrd_success);
     104    TEST_VERIFY_EXIT (thrd_join (thr, NULL) == thrd_success);
     105  }
     106  
     107  static int
     108  do_test (void)
     109  {
     110    check_current_sigmask ("initial mask", (signals) { false, });
     111    check_posix_thread (NULL, (signals) { false, });
     112    check_c11_thread ((signals) { false, });
     113  
     114    sigset_t set;
     115    sigemptyset (&set);
     116    sigaddset (&set, SIGUSR1);
     117    xpthread_sigmask (SIG_SETMASK, &set, NULL);
     118    check_current_sigmask ("SIGUSR1 masked", (signals) { [SIGUSR1] = true, });
     119    /* The signal mask is inherited by the new thread.  */
     120    check_posix_thread (NULL, (signals) { [SIGUSR1] = true, });
     121    check_c11_thread ((signals) { [SIGUSR1] = true, });
     122  
     123    pthread_attr_t attr;
     124    xpthread_attr_init (&attr);
     125    TEST_COMPARE (pthread_attr_getsigmask_np (&attr, &set),
     126                  PTHREAD_ATTR_NO_SIGMASK_NP);
     127    /* By default, the signal mask is inherited (even with an explicit
     128       thread attribute).  */
     129    check_posix_thread (&attr, (signals) { [SIGUSR1] = true, });
     130  
     131    /* Check that pthread_attr_getsigmask_np can obtain the signal
     132       mask.  */
     133    sigemptyset (&set);
     134    sigaddset (&set, SIGUSR2);
     135    TEST_COMPARE (pthread_attr_setsigmask_np (&attr, &set), 0);
     136    sigemptyset (&set);
     137    TEST_COMPARE (pthread_attr_getsigmask_np (&attr, &set), 0);
     138    check_sigmask ("pthread_attr_getsigmask_np", (signals) { [SIGUSR2] = true, },
     139                   &set);
     140  
     141    /* Check that a thread is launched with the configured signal
     142       mask.  */
     143    check_current_sigmask ("SIGUSR1 masked", (signals) { [SIGUSR1] = true, });
     144    check_posix_thread (&attr, (signals) { [SIGUSR2] = true, });
     145    check_current_sigmask ("SIGUSR1 masked", (signals) { [SIGUSR1] = true, });
     146  
     147    /* But C11 threads remain at inheritance.  */
     148    check_c11_thread ((signals) { [SIGUSR1] = true, });
     149  
     150    /* Check that filling the original signal set does not affect thread
     151       creation.  */
     152    sigfillset (&set);
     153    check_posix_thread (&attr, (signals) { [SIGUSR2] = true, });
     154  
     155    /* Check that clearing the signal in the attribute restores
     156       inheritance.  */
     157    TEST_COMPARE (pthread_attr_setsigmask_np (&attr, NULL), 0);
     158    TEST_COMPARE (pthread_attr_getsigmask_np (&attr, &set),
     159                  PTHREAD_ATTR_NO_SIGMASK_NP);
     160    check_posix_thread (&attr, (signals) { [SIGUSR1] = true, });
     161  
     162    /* Mask SIGHUP via the default thread attribute.  */
     163    sigemptyset (&set);
     164    sigaddset (&set, SIGHUP);
     165    TEST_COMPARE (pthread_attr_setsigmask_np (&attr, &set), 0);
     166    TEST_COMPARE (pthread_setattr_default_np (&attr), 0);
     167  
     168    /* Check that the mask was applied to the default attribute.  */
     169    xpthread_attr_destroy (&attr);
     170    TEST_COMPARE (pthread_getattr_default_np (&attr), 0);
     171    sigaddset (&set, SIGHUP);
     172    TEST_COMPARE (pthread_attr_getsigmask_np (&attr, &set), 0);
     173    check_sigmask ("default attribute", (signals) { [SIGHUP] = true, }, &set);
     174    xpthread_attr_destroy (&attr);
     175  
     176    /* Check that the default attribute is applied.  */
     177    check_posix_thread (NULL, (signals) { [SIGHUP] = true, });
     178    check_c11_thread ((signals) { [SIGHUP] = true, });
     179  
     180    /* An explicit attribute with no signal mask triggers inheritance
     181       even if the default has been changed.  */
     182    xpthread_attr_init (&attr);
     183    check_posix_thread (&attr, (signals) { [SIGUSR1] = true, });
     184  
     185    /* Explicitly setting the signal mask affects the new thread even
     186       with a default attribute.  */
     187    sigemptyset (&set);
     188    sigaddset (&set, SIGUSR2);
     189    TEST_COMPARE (pthread_attr_setsigmask_np (&attr, &set), 0);
     190    check_posix_thread (&attr, (signals) { [SIGUSR2] = true, });
     191  
     192    /* Resetting the default attribute brings back the old inheritance
     193       behavior.  */
     194    xpthread_attr_destroy (&attr);
     195    xpthread_attr_init (&attr);
     196    TEST_COMPARE (pthread_setattr_default_np (&attr), 0);
     197    xpthread_attr_destroy (&attr);
     198    check_posix_thread (NULL, (signals) { [SIGUSR1] = true, });
     199    check_c11_thread ((signals) { [SIGUSR1] = true, });
     200  
     201    return 0;
     202  }
     203  
     204  #include <support/test-driver.c>