1 /* Test that raise sends signal to current thread even if blocked.
2    Copyright (C) 2021 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 #include <signal.h>
20 #include <support/check.h>
21 #include <support/xsignal.h>
22 #include <support/xthread.h>
23 #include <pthread.h>
24 #include <unistd.h>
25 
26 /* Used to create a dummy thread ID distinct from all other thread
27    IDs.  */
28 static void *
noop(void * ignored)29 noop (void *ignored)
30 {
31   return NULL;
32 }
33 
34 static volatile pthread_t signal_thread;
35 
36 static void
signal_handler(int signo)37 signal_handler (int signo)
38 {
39   signal_thread = pthread_self ();
40 }
41 
42 /* Used to ensure that waiting_thread has launched and can accept
43    signals.  */
44 static pthread_barrier_t barrier;
45 
46 static void *
waiting_thread(void * ignored)47 waiting_thread (void *ignored)
48 {
49   xpthread_barrier_wait (&barrier);
50   pause ();
51   return NULL;
52 }
53 
54 static int
do_test(void)55 do_test (void)
56 {
57   xsignal (SIGUSR1, signal_handler);
58   xpthread_barrier_init (&barrier, NULL, 2);
59 
60   /* Distinct thread ID value to */
61   pthread_t dummy = xpthread_create (NULL, noop, NULL);
62   signal_thread = dummy;
63 
64   pthread_t helper = xpthread_create (NULL, waiting_thread, NULL);
65 
66   /* Make sure that the thread is running.  */
67   xpthread_barrier_wait (&barrier);
68 
69   /* Block signals on this thread.  */
70   sigset_t set;
71   sigfillset (&set);
72   xpthread_sigmask (SIG_BLOCK, &set, NULL);
73 
74   /* Send the signal to this thread.  It must not be delivered.  */
75   raise (SIGUSR1);
76   TEST_VERIFY (signal_thread == dummy);
77 
78   /* Wait a bit to give a chance for signal delivery (increases
79      chances of failure with bug 28407).  */
80   usleep (50 * 1000);
81 
82   /* Unblocking should cause synchronous delivery of the signal.  */
83   xpthread_sigmask (SIG_UNBLOCK, &set, NULL);
84   TEST_VERIFY (signal_thread == pthread_self ());
85 
86   xpthread_cancel (helper);
87   xpthread_join (helper);
88   xpthread_join (dummy);
89   return 0;
90 }
91 
92 #include <support/test-driver.c>
93