• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Jiri Palecek<jpalecek@web.de>, 2009
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of version 2 of the GNU General Public License as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it would be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  *
12  * Further, this software is distributed without any warranty that it is
13  * free of the rightful claim of any third person regarding infringement
14  * or the like.  Any license provided herein, whether implied or
15  * otherwise, applies only to this software file.  Patent licenses, if
16  * any, provided herein do not apply to combinations of this program with
17  * other software, or any other product whatsoever.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 #include "test.h"
24 #include <errno.h>
25 #include <signal.h>
26 #include "../utils/include_j_h.h"
27 #include "../utils/common_j_h.c"
28 #include <limits.h>
29 #include "lapi/syscalls.h"
30 
31 #define SUCCEED_OR_DIE(syscall, message, ...)				 \
32 	(errno = 0,							 \
33 		({int ret=syscall(__VA_ARGS__);				 \
34 			if (ret==-1)					 \
35 				tst_brkm(TBROK|TERRNO, cleanup, message);\
36 			ret;}))
37 
38 /* Report success iff TEST_RETURN and TEST_ERRNO are equal to
39 	 exp_return and exp_errno, resp., and cond is true. If cond is not
40 	 true, report condition_errmsg
41 */
report_success_cond(const char * func,const char * file,int line,long exp_return,int exp_errno,int condition,char * condition_errmsg)42 static void report_success_cond(const char *func, const char *file, int line,
43 				long exp_return, int exp_errno, int condition,
44 				char *condition_errmsg)
45 {
46 	if (exp_return == TEST_RETURN
47 	    && (exp_return != -1 || exp_errno == TEST_ERRNO))
48 		if (condition)
49 			tst_resm(TPASS, "Test passed");
50 		else
51 			tst_resm(TFAIL, "%s (%s: %d): %s", func, file, line,
52 				 condition_errmsg);
53 	else if (TEST_RETURN != -1)
54 		tst_resm(TFAIL,
55 			 "%s (%s: %d): Unexpected return value; expected %ld, got %ld",
56 			 func, file, line, exp_return, TEST_RETURN);
57 	else
58 		tst_resm(TFAIL | TTERRNO, "%s (%s: %d): Unexpected failure",
59 			 func, file, line);
60 }
61 
62 #define REPORT_SUCCESS_COND(exp_return, exp_errno, condition, condition_errmsg)	\
63 	report_success_cond(__FUNCTION__, __FILE__, __LINE__, exp_return, exp_errno, condition, condition_errmsg);
64 
65 /* Report success iff TEST_RETURN and TEST_ERRNO are equal to
66 	 exp_return and exp_errno, resp.
67 */
68 #define REPORT_SUCCESS(exp_return, exp_errno)					\
69 	REPORT_SUCCESS_COND(exp_return, exp_errno, 1, "");
70 
71 static void cleanup(void);
72 
empty_handler(int sig)73 static void empty_handler(int sig)
74 {
75 }
76 
setup(void)77 static void setup(void)
78 {
79 	tst_sig(FORK, DEF_HANDLER, cleanup);
80 	signal(SIGUSR1, empty_handler);
81 	signal(SIGALRM, empty_handler);
82 	signal(SIGUSR2, SIG_IGN);
83 
84 	TEST_PAUSE;
85 }
86 
cleanup(void)87 static void cleanup(void)
88 {
89 }
90 
91 typedef int (*swi_func) (const sigset_t * set, siginfo_t * info,
92 			 struct timespec * timeout);
93 typedef void (*test_func) (swi_func, int);
94 
95 #ifdef TEST_SIGWAIT
my_sigwait(const sigset_t * set,siginfo_t * info,struct timespec * timeout)96 static int my_sigwait(const sigset_t * set, siginfo_t * info,
97 		      struct timespec *timeout)
98 {
99 	int ret;
100 	int err = sigwait(set, &ret);
101 
102 	if (err == 0)
103 		return ret;
104 	errno = err;
105 	return -1;
106 }
107 #endif
108 
109 #ifdef TEST_SIGWAITINFO
my_sigwaitinfo(const sigset_t * set,siginfo_t * info,struct timespec * timeout)110 static int my_sigwaitinfo(const sigset_t * set, siginfo_t * info,
111 			  struct timespec *timeout)
112 {
113 
114 	return sigwaitinfo(set, info);
115 }
116 #endif
117 
118 #ifdef TEST_SIGTIMEDWAIT
my_sigtimedwait(const sigset_t * set,siginfo_t * info,struct timespec * timeout)119 static int my_sigtimedwait(const sigset_t * set, siginfo_t * info,
120 			   struct timespec *timeout)
121 {
122 
123 	return sigtimedwait(set, info, timeout);
124 }
125 #endif
126 
127 #ifdef TEST_RT_SIGTIMEDWAIT
my_rt_sigtimedwait(const sigset_t * set,siginfo_t * info,struct timespec * timeout)128 static int my_rt_sigtimedwait(const sigset_t * set, siginfo_t * info,
129 			      struct timespec *timeout)
130 {
131 
132 	/* The last argument is (number_of_signals)/(bits_per_byte), which are 64 and 8, resp. */
133 	return ltp_syscall(__NR_rt_sigtimedwait, set, info, timeout, 8);
134 }
135 #endif
136 
test_empty_set(swi_func sigwaitinfo,int signo)137 void test_empty_set(swi_func sigwaitinfo, int signo)
138 {
139 	sigset_t sigs;
140 	siginfo_t si;
141 	pid_t child;
142 
143 	SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
144 	/* Run a child that will wake us up */
145 	child = create_sig_proc(100000, signo, UINT_MAX);
146 
147 	TEST(sigwaitinfo(&sigs, &si, NULL));
148 	REPORT_SUCCESS(-1, EINTR);
149 
150 	kill(child, SIGTERM);
151 }
152 
test_timeout(swi_func sigwaitinfo,int signo)153 void test_timeout(swi_func sigwaitinfo, int signo)
154 {
155 	sigset_t sigs;
156 	siginfo_t si;
157 	pid_t child;
158 	struct timespec ts = {.tv_sec = 1 };
159 
160 	SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
161 
162 	/* Run a child that will wake us up */
163 	child = create_sig_proc(100000, signo, UINT_MAX);
164 
165 	TEST(sigwaitinfo(&sigs, &si, &ts));
166 	REPORT_SUCCESS(-1, EAGAIN);
167 
168 	kill(child, SIGTERM);
169 }
170 
171 /* Note: sigwait-ing for a signal that is not blocked is unspecified
172  * by POSIX; but works for non-ignored signals under Linux
173  */
test_unmasked_matching(swi_func sigwaitinfo,int signo)174 void test_unmasked_matching(swi_func sigwaitinfo, int signo)
175 {
176 	sigset_t sigs;
177 	siginfo_t si;
178 	pid_t child;
179 
180 	SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
181 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo);
182 
183 	/* Run a child that will wake us up */
184 	child = create_sig_proc(100000, signo, UINT_MAX);
185 
186 	TEST(sigwaitinfo(&sigs, &si, NULL));
187 	REPORT_SUCCESS_COND(signo, 0, si.si_pid == child
188 			    && si.si_code == SI_USER
189 			    && si.si_signo == signo, "Struct siginfo mismatch");
190 
191 	kill(child, SIGTERM);
192 }
193 
test_unmasked_matching_noinfo(swi_func sigwaitinfo,int signo)194 void test_unmasked_matching_noinfo(swi_func sigwaitinfo, int signo)
195 {
196 	sigset_t sigs;
197 	pid_t child;
198 
199 	SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
200 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo);
201 	/* Run a child that will wake us up */
202 	child = create_sig_proc(100000, signo, UINT_MAX);
203 
204 	TEST(sigwaitinfo(&sigs, NULL, NULL));
205 	REPORT_SUCCESS(signo, 0);
206 
207 	kill(child, SIGTERM);
208 }
209 
test_masked_matching(swi_func sigwaitinfo,int signo)210 void test_masked_matching(swi_func sigwaitinfo, int signo)
211 {
212 	sigset_t sigs, oldmask;
213 	siginfo_t si;
214 	pid_t child;
215 
216 	SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
217 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo);
218 	/* let's not get interrupted by our dying child */
219 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, SIGCHLD);
220 
221 	SUCCEED_OR_DIE(sigprocmask, "sigprocmask failed", SIG_SETMASK, &sigs,
222 		       &oldmask);
223 
224 	/* don't wait on a SIGCHLD */
225 	SUCCEED_OR_DIE(sigdelset, "sigaddset failed", &sigs, SIGCHLD);
226 
227 	/* Run a child that will wake us up */
228 	child = create_sig_proc(0, signo, 1);
229 
230 	TEST(sigwaitinfo(&sigs, &si, NULL));
231 	REPORT_SUCCESS_COND(signo, 0, si.si_pid == child
232 			    && si.si_code == SI_USER
233 			    && si.si_signo == signo, "Struct siginfo mismatch");
234 
235 	SUCCEED_OR_DIE(sigprocmask, "restoring original signal mask failed",
236 		       SIG_SETMASK, &oldmask, &oldmask);
237 
238 	tst_count--;
239 
240 	if (sigismember(&oldmask, signo))
241 		tst_resm(TPASS, "sigwaitinfo restored the original mask");
242 	else
243 		tst_resm(TFAIL,
244 			 "sigwaitinfo failed to restore the original mask");
245 }
246 
test_masked_matching_rt(swi_func sigwaitinfo,int signo)247 void test_masked_matching_rt(swi_func sigwaitinfo, int signo)
248 {
249 	sigset_t sigs, oldmask;
250 	siginfo_t si;
251 	pid_t child[2];
252 	int status;
253 
254 	signo = SIGRTMIN + 1;
255 
256 	SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
257 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo);
258 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo + 1);
259 	/* let's not get interrupted by our dying child */
260 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, SIGCHLD);
261 
262 	SUCCEED_OR_DIE(sigprocmask, "sigprocmask failed", SIG_SETMASK, &sigs,
263 		       &oldmask);
264 
265 	/* don't wait on a SIGCHLD */
266 	SUCCEED_OR_DIE(sigdelset, "sigdelset failed", &sigs, SIGCHLD);
267 
268 	/* Run a child that will wake us up */
269 	child[0] = create_sig_proc(0, signo, 1);
270 	child[1] = create_sig_proc(0, signo + 1, 1);
271 
272 	/* Ensure that the signals have been sent */
273 	waitpid(child[0], &status, 0);
274 	waitpid(child[1], &status, 0);
275 
276 	TEST(sigwaitinfo(&sigs, &si, NULL));
277 	REPORT_SUCCESS_COND(signo, 0, si.si_pid == child[0]
278 			    && si.si_code == SI_USER
279 			    && si.si_signo == signo, "Struct siginfo mismatch");
280 
281 	/* eat the other signal */
282 	tst_count--;
283 	TEST(sigwaitinfo(&sigs, &si, NULL));
284 	REPORT_SUCCESS_COND(signo + 1, 0, si.si_pid == child[1]
285 			    && si.si_code == SI_USER
286 			    && si.si_signo == signo + 1,
287 			    "Struct siginfo mismatch");
288 
289 	SUCCEED_OR_DIE(sigprocmask, "restoring original signal mask failed",
290 		       SIG_SETMASK, &oldmask, &oldmask);
291 
292 	tst_count--;
293 
294 	if (sigismember(&oldmask, signo))
295 		tst_resm(TPASS, "sigwaitinfo restored the original mask");
296 	else
297 		tst_resm(TFAIL,
298 			 "sigwaitinfo failed to restore the original mask");
299 }
300 
test_masked_matching_noinfo(swi_func sigwaitinfo,int signo)301 void test_masked_matching_noinfo(swi_func sigwaitinfo, int signo)
302 {
303 	sigset_t sigs, oldmask;
304 	pid_t child;
305 
306 	SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
307 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo);
308 	/* let's not get interrupted by our dying child */
309 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, SIGCHLD);
310 
311 	SUCCEED_OR_DIE(sigprocmask, "sigprocmask failed", SIG_SETMASK, &sigs,
312 		       &oldmask);
313 
314 	/* don't wait on a SIGCHLD */
315 	SUCCEED_OR_DIE(sigdelset, "sigaddset failed", &sigs, SIGCHLD);
316 
317 	/* Run a child that will wake us up */
318 	child = create_sig_proc(0, signo, 1);
319 
320 	TEST(sigwaitinfo(&sigs, NULL, NULL));
321 	REPORT_SUCCESS(signo, 0);
322 
323 	SUCCEED_OR_DIE(sigprocmask, "restoring original signal mask failed",
324 		       SIG_SETMASK, &oldmask, &oldmask);
325 
326 	tst_count--;
327 
328 	if (sigismember(&oldmask, signo))
329 		tst_resm(TPASS, "sigwaitinfo restored the original mask");
330 	else
331 		tst_resm(TFAIL,
332 			 "sigwaitinfo failed to restore the original mask");
333 
334 }
335 
test_bad_address(swi_func sigwaitinfo,int signo)336 void test_bad_address(swi_func sigwaitinfo, int signo)
337 {
338 	sigset_t sigs, oldmask;
339 	pid_t child;
340 
341 	SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
342 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo);
343 	/* let's not get interrupted by our dying child */
344 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, SIGCHLD);
345 
346 	SUCCEED_OR_DIE(sigprocmask, "sigprocmask failed", SIG_SETMASK, &sigs,
347 		       &oldmask);
348 
349 	/* don't wait on a SIGCHLD */
350 	SUCCEED_OR_DIE(sigdelset, "sigaddset failed", &sigs, SIGCHLD);
351 
352 	/* Run a child that will wake us up */
353 	child = create_sig_proc(0, signo, 1);
354 
355 	TEST(sigwaitinfo(&sigs, (void *)1, NULL));
356 	REPORT_SUCCESS(-1, EFAULT);
357 
358 	SUCCEED_OR_DIE(sigprocmask, "sigprocmask failed", SIG_SETMASK, &oldmask,
359 		       &oldmask);
360 
361 	kill(child, SIGTERM);
362 }
363 
test_bad_address2(swi_func sigwaitinfo,int signo)364 void test_bad_address2(swi_func sigwaitinfo, int signo)
365 {
366 	pid_t pid;
367 	int status;
368 
369 	switch (pid = fork()) {
370 	case -1:
371 		tst_brkm(TBROK | TERRNO, NULL, "fork() failed");
372 	case 0:
373 		signal(SIGSEGV, SIG_DFL);
374 
375 		/*
376 		 * depending on glibc implementation we should
377 		 * either crash or get EFAULT
378 		 */
379 		TEST(sigwaitinfo((void *)1, NULL, NULL));
380 
381 		if (TEST_RETURN == -1 && TEST_ERRNO == EFAULT)
382 			_exit(0);
383 
384 		tst_resm(TINFO | TTERRNO, "swi_func returned: %ld",
385 			TEST_RETURN);
386 		_exit(1);
387 		break;
388 	default:
389 		break;
390 	}
391 
392 	SUCCEED_OR_DIE(waitpid, "waitpid failed", pid, &status, 0);
393 
394 	if ((WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV)
395 		|| (WIFEXITED(status) && WEXITSTATUS(status) == 0)) {
396 		tst_resm(TPASS, "Test passed");
397 		return;
398 	}
399 
400 	if (WIFEXITED(status)) {
401 		tst_resm(TFAIL, "Unrecognised child exit code: %d",
402 			WEXITSTATUS(status));
403 	}
404 	if (WIFSIGNALED(status)) {
405 		tst_resm(TFAIL, "Unrecognised child termsig: %d",
406 			WTERMSIG(status));
407 	}
408 }
409 
test_bad_address3(swi_func sigwaitinfo,int signo)410 void test_bad_address3(swi_func sigwaitinfo, int signo)
411 {
412 	sigset_t sigs;
413 	SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
414 
415 	TEST(sigwaitinfo(&sigs, NULL, (void *)1));
416 	REPORT_SUCCESS(-1, EFAULT);
417 }
418 
419 struct test_desc {
420 	test_func tf;
421 	swi_func swi;
422 	int signo;
423 } tests[] = {
424 #ifdef TEST_RT_SIGTIMEDWAIT
425 	{
426 	test_empty_set, my_rt_sigtimedwait, SIGUSR1}, {
427 	test_unmasked_matching, my_rt_sigtimedwait, SIGUSR1}, {
428 	test_masked_matching, my_rt_sigtimedwait, SIGUSR1}, {
429 	test_unmasked_matching_noinfo, my_rt_sigtimedwait, SIGUSR1}, {
430 	test_masked_matching_noinfo, my_rt_sigtimedwait, SIGUSR1}, {
431 	test_bad_address, my_rt_sigtimedwait, SIGUSR1}, {
432 	test_bad_address2, my_rt_sigtimedwait, SIGUSR1}, {
433 	test_bad_address3, my_rt_sigtimedwait, SIGUSR1}, {
434 	test_timeout, my_rt_sigtimedwait, 0},
435 	    /* Special cases */
436 	    /* 1: sigwaitinfo does respond to ignored signal */
437 	{
438 	test_masked_matching, my_rt_sigtimedwait, SIGUSR2},
439 	    /* 2: An ignored signal doesn't cause sigwaitinfo to return EINTR */
440 	{
441 	test_timeout, my_rt_sigtimedwait, SIGUSR2},
442 	    /* 3: The handler is not called when the signal is waited for by sigwaitinfo */
443 	{
444 	test_masked_matching, my_rt_sigtimedwait, SIGTERM},
445 	    /* 4: Simultaneous realtime signals are delivered in the order of increasing signal number */
446 #if !(defined(ANDROID) && !defined(__LP64__))
447 	{
448 	test_masked_matching_rt, my_rt_sigtimedwait, -1},
449 #endif
450 #endif
451 #if defined TEST_SIGWAIT
452 	{
453 	test_unmasked_matching_noinfo, my_sigwait, SIGUSR1}, {
454 	test_masked_matching_noinfo, my_sigwait, SIGUSR1},
455 #endif
456 #if defined TEST_SIGWAITINFO
457 	{
458 	test_empty_set, my_sigwaitinfo, SIGUSR1}, {
459 	test_unmasked_matching, my_sigwaitinfo, SIGUSR1}, {
460 	test_masked_matching, my_sigwaitinfo, SIGUSR1}, {
461 	test_unmasked_matching_noinfo, my_sigwaitinfo, SIGUSR1}, {
462 	test_masked_matching_noinfo, my_sigwaitinfo, SIGUSR1}, {
463 	test_bad_address, my_sigwaitinfo, SIGUSR1}, {
464 	test_bad_address2, my_sigwaitinfo, SIGUSR1},
465 #endif
466 #if defined TEST_SIGTIMEDWAIT
467 	{
468 	test_empty_set, my_sigtimedwait, SIGUSR1}, {
469 	test_unmasked_matching, my_sigtimedwait, SIGUSR1}, {
470 	test_masked_matching, my_sigtimedwait, SIGUSR1}, {
471 	test_unmasked_matching_noinfo, my_sigtimedwait, SIGUSR1}, {
472 	test_masked_matching_noinfo, my_sigtimedwait, SIGUSR1}, {
473 	test_bad_address, my_sigtimedwait, SIGUSR1}, {
474 	test_bad_address2, my_sigtimedwait, SIGUSR1}, {
475 	test_bad_address3, my_sigtimedwait, SIGUSR1}, {
476 	test_timeout, my_sigtimedwait, 0},
477 #endif
478 };
479 
480 #if defined TEST_SIGWAITINFO
481 const char *TCID = "sigwaitinfo01";
482 #elif defined TEST_RT_SIGTIMEDWAIT
483 const char *TCID = "rt_sigtimedwait01";
484 #elif defined TEST_SIGTIMEDWAIT
485 const char *TCID = "sigtimedwait01";
486 #elif defined TEST_SIGWAIT
487 const char *TCID = "sigwait01";
488 #endif
489 
490 int TST_TOTAL = ARRAY_SIZE(tests);
491 
main(int argc,char ** argv)492 int main(int argc, char **argv)
493 {
494 	unsigned i;
495 	int lc;
496 
497 	tst_parse_opts(argc, argv, NULL, NULL);
498 
499 	setup();
500 
501 	for (lc = 0; TEST_LOOPING(lc); ++lc) {
502 		tst_count = 0;
503 
504 		for (i = 0; i < ARRAY_SIZE(tests); i++) {
505 			alarm(10);	/* arrange a 10 second timeout */
506 			tst_resm(TINFO, "%p, %d", tests[i].swi, tests[i].signo);
507 			tests[i].tf(tests[i].swi, tests[i].signo);
508 		}
509 		alarm(0);
510 	}
511 
512 	cleanup();
513 	tst_exit();
514 }
515