(root)/
grep-3.11/
gnulib-tests/
test-pthread_sigmask2.c
       1  /* Test of pthread_sigmask in a multi-threaded program.
       2     Copyright (C) 2011-2023 Free Software Foundation, Inc.
       3  
       4     This program is free software: you can redistribute it and/or modify
       5     it under the terms of the GNU General Public License as published by
       6     the Free Software Foundation, either version 3 of the License, or
       7     (at your option) any later version.
       8  
       9     This program 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
      12     GNU General Public License for more details.
      13  
      14     You should have received a copy of the GNU General Public License
      15     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      16  
      17  /* Written by Bruno Haible <bruno@clisp.org>, 2011.  */
      18  
      19  #include <config.h>
      20  
      21  #include <signal.h>
      22  
      23  #include <errno.h>
      24  #include <pthread.h>
      25  #include <stdio.h>
      26  #include <unistd.h>
      27  
      28  #include "macros.h"
      29  
      30  #if USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS
      31  
      32  static pthread_t main_thread;
      33  static pthread_t killer_thread;
      34  
      35  static void *
      36  killer_thread_func (void *arg)
      37  {
      38    sleep (1);
      39    pthread_kill (main_thread, SIGINT);
      40    return NULL;
      41  }
      42  
      43  static volatile int sigint_occurred;
      44  
      45  static void
      46  sigint_handler (int sig)
      47  {
      48    sigint_occurred++;
      49  }
      50  
      51  int
      52  main (int argc, char *argv[])
      53  {
      54    sigset_t set;
      55  
      56    signal (SIGINT, sigint_handler);
      57  
      58    sigemptyset (&set);
      59    sigaddset (&set, SIGINT);
      60  
      61    /* Check error handling.  */
      62    /* This call returns 0 on NetBSD 8.0.  */
      63  #if !defined __NetBSD__
      64    ASSERT (pthread_sigmask (1729, &set, NULL) == EINVAL);
      65  #endif
      66  
      67    /* Block SIGINT.  */
      68    ASSERT (pthread_sigmask (SIG_BLOCK, &set, NULL) == 0);
      69  
      70    /* Request a SIGINT signal from another thread.  */
      71    main_thread = pthread_self ();
      72    ASSERT (pthread_create (&killer_thread, NULL, killer_thread_func, NULL) == 0);
      73  
      74    /* Wait.  */
      75    sleep (2);
      76  
      77    /* The signal should not have arrived yet, because it is blocked.  */
      78    ASSERT (sigint_occurred == 0);
      79  
      80    /* Unblock SIGINT.  */
      81    ASSERT (pthread_sigmask (SIG_UNBLOCK, &set, NULL) == 0);
      82  
      83    /* The signal should have arrived now, because POSIX says
      84         "If there are any pending unblocked signals after the call to
      85          pthread_sigmask(), at least one of those signals shall be delivered
      86          before the call to pthread_sigmask() returns."  */
      87    ASSERT (sigint_occurred == 1);
      88  
      89    /* Clean up the thread.  This avoid a "ThreadSanitizer: thread leak" warning
      90       from "gcc -fsanitize=thread".  */
      91    ASSERT (pthread_join (killer_thread, NULL) == 0);
      92  
      93    return 0;
      94  }
      95  
      96  #else
      97  
      98  int
      99  main ()
     100  {
     101    fputs ("Skipping test: POSIX threads not enabled\n", stderr);
     102    return 77;
     103  }
     104  
     105  #endif