Switch to UTF-8 for INSTALL
[glibc.git] / sysdeps / pthread / tst-pthread_kill-exiting.c
blobd9316cc112791208afe17c2778eb22ba0ea5d67b
1 /* Test that pthread_kill succeeds during thread exit.
2 Copyright (C) 2021-2023 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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/>. */
19 /* This test verifies that pthread_kill for a thread that is exiting
20 succeeds (with or without actually delivering the signal). */
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>
29 /* Set to true by timeout_thread_function when the test should
30 terminate. */
31 static bool timeout;
33 static void *
34 timeout_thread_function (void *unused)
36 usleep (1000 * 1000);
37 __atomic_store_n (&timeout, true, __ATOMIC_RELAXED);
38 return NULL;
41 /* Used to synchronize the sending threads with the target thread and
42 main thread. */
43 static pthread_barrier_t barrier_1;
44 static pthread_barrier_t barrier_2;
46 /* The target thread to which signals are to be sent. */
47 static pthread_t target_thread;
49 /* Set by the main thread to true after timeout has been set to
50 true. */
51 static bool exiting;
53 static void *
54 sender_thread_function (void *unused)
56 while (true)
58 /* Wait until target_thread has been initialized. The target
59 thread and main thread participate in this barrier. */
60 xpthread_barrier_wait (&barrier_1);
62 if (exiting)
63 break;
65 xpthread_kill (target_thread, SIGUSR1);
67 /* Communicate that the signal has been sent. The main thread
68 participates in this barrier. */
69 xpthread_barrier_wait (&barrier_2);
71 return NULL;
74 static void *
75 target_thread_function (void *unused)
77 target_thread = pthread_self ();
78 xpthread_barrier_wait (&barrier_1);
79 return NULL;
82 static int
83 do_test (void)
85 xsignal (SIGUSR1, SIG_IGN);
87 pthread_t thr_timeout = xpthread_create (NULL, timeout_thread_function, NULL);
89 pthread_t threads[4];
90 xpthread_barrier_init (&barrier_1, NULL, array_length (threads) + 2);
91 xpthread_barrier_init (&barrier_2, NULL, array_length (threads) + 1);
93 for (int i = 0; i < array_length (threads); ++i)
94 threads[i] = xpthread_create (NULL, sender_thread_function, NULL);
96 while (!__atomic_load_n (&timeout, __ATOMIC_RELAXED))
98 xpthread_create (NULL, target_thread_function, NULL);
100 /* Wait for the target thread to be set up and signal sending to
101 start. */
102 xpthread_barrier_wait (&barrier_1);
104 /* Wait for signal sending to complete. */
105 xpthread_barrier_wait (&barrier_2);
107 xpthread_join (target_thread);
110 exiting = true;
112 /* Signal the sending threads to exit. */
113 xpthread_create (NULL, target_thread_function, NULL);
114 xpthread_barrier_wait (&barrier_1);
116 for (int i = 0; i < array_length (threads); ++i)
117 xpthread_join (threads[i]);
118 xpthread_join (thr_timeout);
120 return 0;
123 #include <support/test-driver.c>