elf/Makefile: Split and sort PIE tests
[glibc.git] / sysdeps / unix / sysv / linux / tst-tgkill.c
blob054bf7fe40779dcfde1dfbdc209835296da7a4df
1 /* Smoke test for the tgkill system call.
2 Copyright (C) 2019-2024 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 #include <errno.h>
20 #include <signal.h>
21 #include <support/check.h>
22 #include <support/namespace.h>
23 #include <support/xthread.h>
24 #include <unistd.h>
26 /* Number of times sigusr1_handler has been invoked. */
27 static volatile sig_atomic_t signals_delivered;
29 /* Expected TID of the thread receiving the signal. */
30 static pid_t expected_signal_tid;
32 static void
33 sigusr1_handler (int signo)
35 TEST_COMPARE (expected_signal_tid, gettid ());
36 ++signals_delivered;
39 struct pid_and_tid
41 pid_t pid;
42 pid_t tid;
45 /* Send signals from the subprocess which are not expected to be
46 delivered. There is no handler for SIGUSR2, so delivery will
47 result in a test failure. CLOSURE must point to a valid PID/TID
48 combination that is still running. */
49 static void
50 subprocess_no_tid_match (void *closure)
52 struct pid_and_tid *ids = closure;
53 TEST_COMPARE (tgkill (ids->pid, gettid (), SIGUSR2), -1);
54 TEST_COMPARE (errno, ESRCH);
56 TEST_COMPARE (tgkill (getpid (), ids->tid, SIGUSR2), -1);
57 TEST_COMPARE (errno, ESRCH);
59 TEST_COMPARE (tgkill (getppid (), gettid (), SIGUSR2), -1);
60 TEST_COMPARE (errno, ESRCH);
63 /* Called from threadfunc below. */
64 static void
65 subprocess (void *closure)
67 int original_tid = expected_signal_tid;
69 /* Do not expect that the following signals are delivered to the
70 subprocess. The parent process retains the original
71 expected_signal_tid value. */
72 expected_signal_tid = 0;
73 TEST_COMPARE (tgkill (getpid (), original_tid, SIGUSR1), -1);
74 TEST_COMPARE (errno, ESRCH);
75 TEST_COMPARE (tgkill (getppid (), gettid (), SIGUSR1), -1);
76 TEST_COMPARE (errno, ESRCH);
77 TEST_COMPARE (expected_signal_tid, 0);
79 /* This call has the correct PID/TID combination and is therefore
80 expected to succeed. */
81 TEST_COMPARE (tgkill (getppid (), original_tid, SIGUSR1), 0);
84 static void *
85 threadfunc (void *closure)
87 TEST_VERIFY (gettid () != getpid ());
88 expected_signal_tid = gettid ();
89 TEST_COMPARE (tgkill (getpid (), gettid (), SIGUSR1), 0);
90 TEST_COMPARE (signals_delivered, 1);
91 signals_delivered = 0;
93 support_isolate_in_subprocess (subprocess, NULL);
95 /* Check that exactly one signal arrived from the subprocess. */
96 TEST_COMPARE (signals_delivered, 1);
98 support_isolate_in_subprocess (subprocess_no_tid_match,
99 &(struct pid_and_tid)
101 .pid = getpid (),
102 .tid = gettid (),
105 support_isolate_in_subprocess (subprocess_no_tid_match,
106 &(struct pid_and_tid)
108 .pid = getpid (),
109 .tid = getpid (),
112 return NULL;
115 static int
116 do_test (void)
118 TEST_VERIFY_EXIT (signal (SIGUSR1, sigusr1_handler) != SIG_ERR);
120 expected_signal_tid = gettid ();
121 TEST_COMPARE (gettid (), getpid ());
122 TEST_COMPARE (tgkill (getpid (), gettid (), SIGUSR1), 0);
123 TEST_COMPARE (signals_delivered, 1);
124 signals_delivered = 0;
126 xpthread_join (xpthread_create (NULL, threadfunc, NULL));
128 TEST_VERIFY (signal (SIGUSR1, SIG_DFL) == sigusr1_handler);
129 return 0;
132 #include <support/test-driver.c>