1/* Test that pthread_kill succeeds during thread exit.
2 Copyright (C) 2021-2024 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 test verifies that pthread_kill for a thread that is exiting
20 succeeds (with or without actually delivering the signal). */
21
22#include <array_length.h>
23#include <stdbool.h>
24#include <stddef.h>
25#include <support/xsignal.h>
26#include <support/xthread.h>
27#include <unistd.h>
28
29/* Set to true by timeout_thread_function when the test should
30 terminate. */
31static bool timeout;
32
33static void *
34timeout_thread_function (void *unused)
35{
36 usleep (useconds: 1000 * 1000);
37 __atomic_store_n (&timeout, true, __ATOMIC_RELAXED);
38 return NULL;
39}
40
41/* Used to synchronize the sending threads with the target thread and
42 main thread. */
43static pthread_barrier_t barrier_1;
44static pthread_barrier_t barrier_2;
45
46/* The target thread to which signals are to be sent. */
47static pthread_t target_thread;
48
49/* Set by the main thread to true after timeout has been set to
50 true. */
51static bool exiting;
52
53static void *
54sender_thread_function (void *unused)
55{
56 while (true)
57 {
58 /* Wait until target_thread has been initialized. The target
59 thread and main thread participate in this barrier. */
60 xpthread_barrier_wait (barrier: &barrier_1);
61
62 if (exiting)
63 break;
64
65 xpthread_kill (thr: target_thread, SIGUSR1);
66
67 /* Communicate that the signal has been sent. The main thread
68 participates in this barrier. */
69 xpthread_barrier_wait (barrier: &barrier_2);
70 }
71 return NULL;
72}
73
74static void *
75target_thread_function (void *unused)
76{
77 target_thread = pthread_self ();
78 xpthread_barrier_wait (barrier: &barrier_1);
79 return NULL;
80}
81
82static int
83do_test (void)
84{
85 xsignal (SIGUSR1, SIG_IGN);
86
87 pthread_t thr_timeout = xpthread_create (NULL, thread_func: timeout_thread_function, NULL);
88
89 pthread_t threads[4];
90 xpthread_barrier_init (barrier: &barrier_1, NULL, array_length (threads) + 2);
91 xpthread_barrier_init (barrier: &barrier_2, NULL, array_length (threads) + 1);
92
93 for (int i = 0; i < array_length (threads); ++i)
94 threads[i] = xpthread_create (NULL, thread_func: sender_thread_function, NULL);
95
96 while (!__atomic_load_n (&timeout, __ATOMIC_RELAXED))
97 {
98 xpthread_create (NULL, thread_func: target_thread_function, NULL);
99
100 /* Wait for the target thread to be set up and signal sending to
101 start. */
102 xpthread_barrier_wait (barrier: &barrier_1);
103
104 /* Wait for signal sending to complete. */
105 xpthread_barrier_wait (barrier: &barrier_2);
106
107 xpthread_join (thr: target_thread);
108 }
109
110 exiting = true;
111
112 /* Signal the sending threads to exit. */
113 xpthread_create (NULL, thread_func: target_thread_function, NULL);
114 xpthread_barrier_wait (barrier: &barrier_1);
115
116 for (int i = 0; i < array_length (threads); ++i)
117 xpthread_join (thr: threads[i]);
118 xpthread_join (thr: thr_timeout);
119
120 return 0;
121}
122
123#include <support/test-driver.c>
124

source code of glibc/sysdeps/pthread/tst-pthread_kill-exiting.c