• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Copyright (c) Jiri Palecek<jpalecek@web.de>, 2009 */
3 
4 #define TST_NO_DEFAULT_MAIN
5 #include <errno.h>
6 #include <stdlib.h>
7 #include <limits.h>
8 #include "lapi/syscalls.h"
9 #include "libsigwait.h"
10 #include "tst_sig_proc.h"
11 
test_empty_set(swi_func sigwaitinfo,int signo,enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)12 void test_empty_set(swi_func sigwaitinfo, int signo,
13 		    enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)
14 {
15 	sigset_t sigs;
16 	siginfo_t si;
17 	pid_t child;
18 
19 	SAFE_SIGEMPTYSET(&sigs);
20 
21 	/* Run a child that will wake us up */
22 	child = create_sig_proc(signo, INT_MAX, 100000);
23 
24 	TEST(sigwaitinfo(&sigs, &si, NULL));
25 	if (TST_RET == -1) {
26 		if (TST_ERR == EINTR)
27 			tst_res(TPASS, "Wait interrupted by expected signal");
28 		else
29 			tst_res(TFAIL | TTERRNO, "Expected error number EINTR, got");
30 	} else {
31 		tst_res(TFAIL, "Expected return value -1, got: %ld", TST_RET);
32 	}
33 
34 	SAFE_KILL(child, SIGTERM);
35 	SAFE_WAIT(NULL);
36 }
37 
test_timeout(swi_func sigwaitinfo,int signo,enum tst_ts_type type)38 void test_timeout(swi_func sigwaitinfo, int signo, enum tst_ts_type type)
39 {
40 	sigset_t sigs;
41 	siginfo_t si;
42 	pid_t child;
43 	struct tst_ts ts;
44 
45 	ts.type = type;
46 	tst_ts_set_sec(&ts, 1);
47 	tst_ts_set_nsec(&ts, 0);
48 
49 	SAFE_SIGEMPTYSET(&sigs);
50 
51 	/* Run a child that will wake us up */
52 	child = create_sig_proc(signo, INT_MAX, 100000);
53 
54 	TEST(sigwaitinfo(&sigs, &si, tst_ts_get(&ts)));
55 	if (TST_RET == -1) {
56 		if (TST_ERR == EAGAIN)
57 			tst_res(TPASS, "Wait interrupted by timeout");
58 		else
59 			tst_res(TFAIL | TTERRNO, "Expected error number EAGAIN, got");
60 	} else {
61 		tst_res(TFAIL, "Expected return value -1, got: %ld", TST_RET);
62 	}
63 
64 	SAFE_KILL(child, SIGTERM);
65 	SAFE_WAIT(NULL);
66 }
67 
68 /* Note: sigwait-ing for a signal that is not blocked is unspecified
69  * by POSIX; but works for non-ignored signals under Linux
70  */
test_unmasked_matching(swi_func sigwaitinfo,int signo,enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)71 void test_unmasked_matching(swi_func sigwaitinfo, int signo,
72 			    enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)
73 {
74 	sigset_t sigs;
75 	siginfo_t si;
76 	pid_t child;
77 
78 	SAFE_SIGEMPTYSET(&sigs);
79 	SAFE_SIGADDSET(&sigs, signo);
80 
81 	/* Run a child that will wake us up */
82 	child = create_sig_proc(signo, INT_MAX, 100000);
83 
84 	TEST(sigwaitinfo(&sigs, &si, NULL));
85 	if (TST_RET == signo) {
86 		if (si.si_pid == child && si.si_code == SI_USER &&
87 		    si.si_signo == signo)
88 			tst_res(TPASS, "struct siginfo is correct");
89 		else
90 			tst_res(TFAIL, "struct siginfo mismatch");
91 	} else {
92 		tst_res(TFAIL | TTERRNO, "sigwaitinfo() failed");
93 	}
94 
95 	SAFE_KILL(child, SIGTERM);
96 	SAFE_WAIT(NULL);
97 }
98 
test_unmasked_matching_noinfo(swi_func sigwaitinfo,int signo,enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)99 void test_unmasked_matching_noinfo(swi_func sigwaitinfo, int signo,
100 				   enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)
101 {
102 	sigset_t sigs;
103 	pid_t child;
104 
105 	SAFE_SIGEMPTYSET(&sigs);
106 	SAFE_SIGADDSET(&sigs, signo);
107 
108 	/* Run a child that will wake us up */
109 	child = create_sig_proc(signo, INT_MAX, 100000);
110 
111 	TEST(sigwaitinfo(&sigs, NULL, NULL));
112 	if (TST_RET == signo)
113 		tst_res(TPASS, "Wait interrupted by expected signal");
114 	else
115 		tst_res(TFAIL | TTERRNO, "sigwaitinfo() failed");
116 
117 	SAFE_KILL(child, SIGTERM);
118 	SAFE_WAIT(NULL);
119 }
120 
test_masked_matching(swi_func sigwaitinfo,int signo,enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)121 void test_masked_matching(swi_func sigwaitinfo, int signo,
122 			  enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)
123 {
124 	sigset_t sigs, oldmask;
125 	siginfo_t si;
126 	pid_t child;
127 
128 	SAFE_SIGEMPTYSET(&sigs);
129 	SAFE_SIGADDSET(&sigs, signo);
130 
131 	/* let's not get interrupted by our dying child */
132 	SAFE_SIGADDSET(&sigs, SIGCHLD);
133 
134 	TEST(sigprocmask(SIG_SETMASK, &sigs, &oldmask));
135 	if (TST_RET == -1)
136 		tst_brk(TBROK | TTERRNO, "sigprocmask() failed");
137 
138 	/* don't wait on a SIGCHLD */
139 	SAFE_SIGDELSET(&sigs, SIGCHLD);
140 
141 	/* Run a child that will wake us up */
142 	child = create_sig_proc(signo, 1, 0);
143 
144 	TEST(sigwaitinfo(&sigs, &si, NULL));
145 	if (TST_RET == signo) {
146 		if (si.si_pid == child && si.si_code == SI_USER &&
147 		    si.si_signo == signo)
148 			tst_res(TPASS, "struct siginfo is correct");
149 		else
150 			tst_res(TFAIL, "struct siginfo mismatch");
151 	} else {
152 		tst_res(TFAIL | TTERRNO, "sigwaitinfo() failed");
153 	}
154 
155 	TEST(sigprocmask(SIG_SETMASK, &oldmask, &sigs));
156 	if (TST_RET == -1)
157 		tst_brk(TBROK | TTERRNO, "restoring original signal mask failed");
158 
159 	if (sigismember(&sigs, signo))
160 		tst_res(TPASS, "sigwaitinfo restored the original mask");
161 	else
162 		tst_res(TFAIL,
163 			 "sigwaitinfo failed to restore the original mask");
164 
165 	SAFE_KILL(child, SIGTERM);
166 	SAFE_WAIT(NULL);
167 }
168 
test_masked_matching_rt(swi_func sigwaitinfo,int signo,enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)169 void test_masked_matching_rt(swi_func sigwaitinfo, int signo,
170 			     enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)
171 {
172 	sigset_t sigs, oldmask;
173 	siginfo_t si;
174 	pid_t child[2];
175 	int status;
176 
177 	signo = SIGRTMIN + 1;
178 
179 	SAFE_SIGEMPTYSET(&sigs);
180 	SAFE_SIGADDSET(&sigs, signo);
181 	SAFE_SIGADDSET(&sigs, signo + 1);
182 
183 	/* let's not get interrupted by our dying child */
184 	SAFE_SIGADDSET(&sigs, SIGCHLD);
185 
186 	TEST(sigprocmask(SIG_SETMASK, &sigs, &oldmask));
187 	if (TST_RET == -1)
188 		tst_brk(TBROK | TTERRNO, "sigprocmask() failed");
189 
190 	/* don't wait on a SIGCHLD */
191 	SAFE_SIGDELSET(&sigs, SIGCHLD);
192 
193 	/* Run a child that will wake us up */
194 	child[0] = create_sig_proc(signo, 1, 0);
195 	child[1] = create_sig_proc(signo + 1, 1, 0);
196 
197 	/* Ensure that the signals have been sent */
198 	SAFE_WAITPID(child[0], &status, 0);
199 	SAFE_WAITPID(child[1], &status, 0);
200 
201 	TEST(sigwaitinfo(&sigs, &si, NULL));
202 	if (TST_RET == signo) {
203 		if (si.si_pid == child[0] && si.si_code == SI_USER &&
204 		    si.si_signo == signo)
205 			tst_res(TPASS, "struct siginfo is correct");
206 		else
207 			tst_res(TFAIL, "struct siginfo mismatch");
208 	} else {
209 		tst_res(TFAIL | TTERRNO, "sigwaitinfo() failed");
210 	}
211 
212 	/* eat the other signal */
213 	TEST(sigwaitinfo(&sigs, &si, NULL));
214 	if (TST_RET == signo + 1) {
215 		if (si.si_pid == child[1] && si.si_code == SI_USER &&
216 		    si.si_signo == signo + 1)
217 			tst_res(TPASS, "struct siginfo is correct");
218 		else
219 			tst_res(TFAIL, "struct siginfo mismatch");
220 	} else {
221 		tst_res(TFAIL | TTERRNO, "sigwaitinfo() failed");
222 	}
223 
224 	TEST(sigprocmask(SIG_SETMASK, &oldmask, &sigs));
225 	if (TST_RET == -1)
226 		tst_brk(TBROK | TTERRNO, "restoring original signal mask failed");
227 
228 	if (sigismember(&sigs, signo))
229 		tst_res(TPASS, "sigwaitinfo restored the original mask");
230 	else
231 		tst_res(TFAIL,
232 			 "sigwaitinfo failed to restore the original mask");
233 }
234 
test_masked_matching_noinfo(swi_func sigwaitinfo,int signo,enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)235 void test_masked_matching_noinfo(swi_func sigwaitinfo, int signo,
236 				 enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)
237 {
238 	sigset_t sigs, oldmask;
239 	pid_t child;
240 
241 	SAFE_SIGEMPTYSET(&sigs);
242 	SAFE_SIGADDSET(&sigs, signo);
243 
244 	/* let's not get interrupted by our dying child */
245 	SAFE_SIGADDSET(&sigs, SIGCHLD);
246 
247 	TEST(sigprocmask(SIG_SETMASK, &sigs, &oldmask));
248 	if (TST_RET == -1)
249 		tst_brk(TBROK | TTERRNO, "sigprocmask() failed");
250 
251 	/* don't wait on a SIGCHLD */
252 	SAFE_SIGDELSET(&sigs, SIGCHLD);
253 
254 	/* Run a child that will wake us up */
255 	child = create_sig_proc(signo, 1, 0);
256 
257 	TEST(sigwaitinfo(&sigs, NULL, NULL));
258 	if (TST_RET == signo)
259 		tst_res(TPASS, "Wait interrupted by expected signal");
260 	else
261 		tst_res(TFAIL | TTERRNO, "sigwaitinfo() failed");
262 
263 	TEST(sigprocmask(SIG_SETMASK, &oldmask, &sigs));
264 	if (TST_RET == -1)
265 		tst_brk(TBROK | TTERRNO, "restoring original signal mask failed");
266 
267 	if (sigismember(&sigs, signo))
268 		tst_res(TPASS, "sigwaitinfo restored the original mask");
269 	else
270 		tst_res(TFAIL,
271 			 "sigwaitinfo failed to restore the original mask");
272 
273 	SAFE_KILL(child, SIGTERM);
274 	SAFE_WAIT(NULL);
275 }
276 
test_bad_address(swi_func sigwaitinfo,int signo,enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)277 void test_bad_address(swi_func sigwaitinfo, int signo,
278 		      enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)
279 {
280 	sigset_t sigs, oldmask;
281 	pid_t child;
282 
283 	SAFE_SIGEMPTYSET(&sigs);
284 	SAFE_SIGADDSET(&sigs, signo);
285 
286 	/* let's not get interrupted by our dying child */
287 	SAFE_SIGADDSET(&sigs, SIGCHLD);
288 
289 	TEST(sigprocmask(SIG_SETMASK, &sigs, &oldmask));
290 	if (TST_RET == -1)
291 		tst_brk(TBROK | TTERRNO, "sigprocmask() failed");
292 
293 	/* don't wait on a SIGCHLD */
294 	SAFE_SIGDELSET(&sigs, SIGCHLD);
295 
296 	/* Run a child that will wake us up */
297 	child = create_sig_proc(signo, 1, 0);
298 
299 	TEST(sigwaitinfo(&sigs, (void *)1, NULL));
300 	if (TST_RET == -1) {
301 		if (TST_ERR == EFAULT)
302 			tst_res(TPASS, "Fault occurred while accessing the buffers");
303 		else
304 			tst_res(TFAIL | TTERRNO, "Expected error number EFAULT, got");
305 	} else {
306 		tst_res(TFAIL, "Expected return value -1, got: %ld", TST_RET);
307 	}
308 
309 	TEST(sigprocmask(SIG_SETMASK, &oldmask, NULL));
310 	if (TST_RET == -1)
311 		tst_brk(TBROK | TTERRNO, "restoring original signal mask failed");
312 
313 	SAFE_KILL(child, SIGTERM);
314 	SAFE_WAIT(NULL);
315 }
316 
test_bad_address2(swi_func sigwaitinfo,int signo LTP_ATTRIBUTE_UNUSED,enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)317 void test_bad_address2(swi_func sigwaitinfo, int signo LTP_ATTRIBUTE_UNUSED,
318 		       enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)
319 {
320 	pid_t pid;
321 	int status;
322 
323 	pid = SAFE_FORK();
324 	if (pid == 0) {
325 		signal(SIGSEGV, SIG_DFL);
326 
327 		/*
328 		 * depending on glibc implementation we should
329 		 * either crash or get EFAULT
330 		 */
331 		TEST(sigwaitinfo((void *)1, NULL, NULL));
332 
333 		if (TST_RET == -1 && TST_ERR == EFAULT)
334 			_exit(0);
335 
336 		tst_res(TINFO | TTERRNO, "swi_func returned: %ld", TST_RET);
337 		_exit(1);
338 	}
339 
340 	SAFE_WAITPID(pid, &status, 0);
341 
342 	if ((WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV)
343 		|| (WIFEXITED(status) && WEXITSTATUS(status) == 0)) {
344 		tst_res(TPASS, "Child exited with expected code");
345 		return;
346 	}
347 
348 	if (WIFEXITED(status)) {
349 		tst_res(TFAIL, "Unrecognised child exit code: %d",
350 			WEXITSTATUS(status));
351 	}
352 	if (WIFSIGNALED(status)) {
353 		tst_res(TFAIL, "Unrecognised child termsig: %d",
354 			WTERMSIG(status));
355 	}
356 }
357 
test_bad_address3(swi_func sigwaitinfo,int signo LTP_ATTRIBUTE_UNUSED,enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)358 void test_bad_address3(swi_func sigwaitinfo, int signo LTP_ATTRIBUTE_UNUSED,
359 		       enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)
360 {
361 	sigset_t sigs;
362 
363 	SAFE_SIGEMPTYSET(&sigs);
364 	TEST(sigwaitinfo(&sigs, NULL, (void *)1));
365 	if (TST_RET == -1) {
366 		if (TST_ERR == EFAULT)
367 			tst_res(TPASS, "Fault occurred while accessing the buffers");
368 		else
369 			tst_res(TFAIL | TTERRNO, "Expected error number EFAULT, got");
370 	} else {
371 		tst_res(TFAIL, "Expected return value -1, got: %ld", TST_RET);
372 	}
373 }
374 
empty_handler(int sig LTP_ATTRIBUTE_UNUSED)375 static void empty_handler(int sig LTP_ATTRIBUTE_UNUSED)
376 {
377 }
378 
sigwait_setup(void)379 void sigwait_setup(void)
380 {
381 	signal(SIGUSR1, empty_handler);
382 	signal(SIGALRM, empty_handler);
383 	signal(SIGUSR2, SIG_IGN);
384 }
385