1 /* Smoke test for the tgkill system call.
2 Copyright (C) 2019-2022 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 <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>
25
26 /* Number of times sigusr1_handler has been invoked. */
27 static volatile sig_atomic_t signals_delivered;
28
29 /* Expected TID of the thread receiving the signal. */
30 static pid_t expected_signal_tid;
31
32 static void
sigusr1_handler(int signo)33 sigusr1_handler (int signo)
34 {
35 TEST_COMPARE (expected_signal_tid, gettid ());
36 ++signals_delivered;
37 }
38
39 struct pid_and_tid
40 {
41 pid_t pid;
42 pid_t tid;
43 };
44
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
subprocess_no_tid_match(void * closure)50 subprocess_no_tid_match (void *closure)
51 {
52 struct pid_and_tid *ids = closure;
53 TEST_COMPARE (tgkill (ids->pid, gettid (), SIGUSR2), -1);
54 TEST_COMPARE (errno, ESRCH);
55
56 TEST_COMPARE (tgkill (getpid (), ids->tid, SIGUSR2), -1);
57 TEST_COMPARE (errno, ESRCH);
58
59 TEST_COMPARE (tgkill (getppid (), gettid (), SIGUSR2), -1);
60 TEST_COMPARE (errno, ESRCH);
61 }
62
63 /* Called from threadfunc below. */
64 static void
subprocess(void * closure)65 subprocess (void *closure)
66 {
67 int original_tid = expected_signal_tid;
68
69 /* Do not expect that the folloing 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);
78
79 /* This call has the correct PID/TID combination and is therefore
80 expected to suceed. */
81 TEST_COMPARE (tgkill (getppid (), original_tid, SIGUSR1), 0);
82 }
83
84 static void *
threadfunc(void * closure)85 threadfunc (void *closure)
86 {
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;
92
93 support_isolate_in_subprocess (subprocess, NULL);
94
95 /* Check that exactly one signal arrived from the subprocess. */
96 TEST_COMPARE (signals_delivered, 1);
97
98 support_isolate_in_subprocess (subprocess_no_tid_match,
99 &(struct pid_and_tid)
100 {
101 .pid = getpid (),
102 .tid = gettid (),
103 });
104
105 support_isolate_in_subprocess (subprocess_no_tid_match,
106 &(struct pid_and_tid)
107 {
108 .pid = getpid (),
109 .tid = getpid (),
110 });
111
112 return NULL;
113 }
114
115 static int
do_test(void)116 do_test (void)
117 {
118 TEST_VERIFY_EXIT (signal (SIGUSR1, sigusr1_handler) != SIG_ERR);
119
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;
125
126 xpthread_join (xpthread_create (NULL, threadfunc, NULL));
127
128 TEST_VERIFY (signal (SIGUSR1, SIG_DFL) == sigusr1_handler);
129 return 0;
130 }
131
132 #include <support/test-driver.c>
133