Home | History | Annotate | Download | only in sigwaitinfo
      1 /*
      2  * Copyright (c) Jiri Palecek<jpalecek (at) 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 "linux_syscall_numbers.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 */
     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 
     73 static void empty_handler(int sig)
     74 {
     75 }
     76 
     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 
     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
     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
    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
    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
    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 
    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 
    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  */
    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 
    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 
    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 
    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 
    253 	signo = SIGRTMIN + 1;
    254 
    255 	SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
    256 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo);
    257 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo + 1);
    258 	/* let's not get interrupted by our dying child */
    259 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, SIGCHLD);
    260 
    261 	SUCCEED_OR_DIE(sigprocmask, "sigprocmask failed", SIG_SETMASK, &sigs,
    262 		       &oldmask);
    263 
    264 	/* don't wait on a SIGCHLD */
    265 	SUCCEED_OR_DIE(sigdelset, "sigdelset failed", &sigs, SIGCHLD);
    266 
    267 	/* Run a child that will wake us up */
    268 	child[0] = create_sig_proc(0, signo, 1);
    269 	child[1] = create_sig_proc(0, signo + 1, 1);
    270 
    271 	TEST(sigwaitinfo(&sigs, &si, NULL));
    272 	REPORT_SUCCESS_COND(signo, 0, si.si_pid == child[0]
    273 			    && si.si_code == SI_USER
    274 			    && si.si_signo == signo, "Struct siginfo mismatch");
    275 
    276 	/* eat the other signal */
    277 	tst_count--;
    278 	TEST(sigwaitinfo(&sigs, &si, NULL));
    279 	REPORT_SUCCESS_COND(signo + 1, 0, si.si_pid == child[1]
    280 			    && si.si_code == SI_USER
    281 			    && si.si_signo == signo + 1,
    282 			    "Struct siginfo mismatch");
    283 
    284 	SUCCEED_OR_DIE(sigprocmask, "restoring original signal mask failed",
    285 		       SIG_SETMASK, &oldmask, &oldmask);
    286 
    287 	tst_count--;
    288 
    289 	if (sigismember(&oldmask, signo))
    290 		tst_resm(TPASS, "sigwaitinfo restored the original mask");
    291 	else
    292 		tst_resm(TFAIL,
    293 			 "sigwaitinfo failed to restore the original mask");
    294 }
    295 
    296 void test_masked_matching_noinfo(swi_func sigwaitinfo, int signo)
    297 {
    298 	sigset_t sigs, oldmask;
    299 	pid_t child;
    300 
    301 	SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
    302 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo);
    303 	/* let's not get interrupted by our dying child */
    304 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, SIGCHLD);
    305 
    306 	SUCCEED_OR_DIE(sigprocmask, "sigprocmask failed", SIG_SETMASK, &sigs,
    307 		       &oldmask);
    308 
    309 	/* don't wait on a SIGCHLD */
    310 	SUCCEED_OR_DIE(sigdelset, "sigaddset failed", &sigs, SIGCHLD);
    311 
    312 	/* Run a child that will wake us up */
    313 	child = create_sig_proc(0, signo, 1);
    314 
    315 	TEST(sigwaitinfo(&sigs, NULL, NULL));
    316 	REPORT_SUCCESS(signo, 0);
    317 
    318 	SUCCEED_OR_DIE(sigprocmask, "restoring original signal mask failed",
    319 		       SIG_SETMASK, &oldmask, &oldmask);
    320 
    321 	tst_count--;
    322 
    323 	if (sigismember(&oldmask, signo))
    324 		tst_resm(TPASS, "sigwaitinfo restored the original mask");
    325 	else
    326 		tst_resm(TFAIL,
    327 			 "sigwaitinfo failed to restore the original mask");
    328 
    329 }
    330 
    331 void test_bad_address(swi_func sigwaitinfo, int signo)
    332 {
    333 	sigset_t sigs, oldmask;
    334 	pid_t child;
    335 
    336 	SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
    337 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo);
    338 	/* let's not get interrupted by our dying child */
    339 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, SIGCHLD);
    340 
    341 	SUCCEED_OR_DIE(sigprocmask, "sigprocmask failed", SIG_SETMASK, &sigs,
    342 		       &oldmask);
    343 
    344 	/* don't wait on a SIGCHLD */
    345 	SUCCEED_OR_DIE(sigdelset, "sigaddset failed", &sigs, SIGCHLD);
    346 
    347 	/* Run a child that will wake us up */
    348 	child = create_sig_proc(0, signo, 1);
    349 
    350 	TEST(sigwaitinfo(&sigs, (void *)1, NULL));
    351 	REPORT_SUCCESS(-1, EFAULT);
    352 
    353 	SUCCEED_OR_DIE(sigprocmask, "sigprocmask failed", SIG_SETMASK, &oldmask,
    354 		       &oldmask);
    355 
    356 	kill(child, SIGTERM);
    357 }
    358 
    359 void test_bad_address2(swi_func sigwaitinfo, int signo)
    360 {
    361 	TEST(sigwaitinfo((void *)1, NULL, NULL));
    362 	REPORT_SUCCESS(-1, EFAULT);
    363 }
    364 
    365 void test_bad_address3(swi_func sigwaitinfo, int signo)
    366 {
    367 	sigset_t sigs;
    368 	SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
    369 
    370 	TEST(sigwaitinfo(&sigs, NULL, (void *)1));
    371 	REPORT_SUCCESS(-1, EFAULT);
    372 }
    373 
    374 struct test_desc {
    375 	test_func tf;
    376 	swi_func swi;
    377 	int signo;
    378 } tests[] = {
    379 #ifdef TEST_RT_SIGTIMEDWAIT
    380 	{
    381 	test_empty_set, my_rt_sigtimedwait, SIGUSR1}, {
    382 	test_unmasked_matching, my_rt_sigtimedwait, SIGUSR1}, {
    383 	test_masked_matching, my_rt_sigtimedwait, SIGUSR1}, {
    384 	test_unmasked_matching_noinfo, my_rt_sigtimedwait, SIGUSR1}, {
    385 	test_masked_matching_noinfo, my_rt_sigtimedwait, SIGUSR1}, {
    386 	test_bad_address, my_rt_sigtimedwait, SIGUSR1}, {
    387 	test_bad_address2, my_rt_sigtimedwait, SIGUSR1}, {
    388 	test_bad_address3, my_rt_sigtimedwait, SIGUSR1}, {
    389 	test_timeout, my_rt_sigtimedwait, 0},
    390 	    /* Special cases */
    391 	    /* 1: sigwaitinfo does respond to ignored signal */
    392 	{
    393 	test_masked_matching, my_rt_sigtimedwait, SIGUSR2},
    394 	    /* 2: An ignored signal doesn't cause sigwaitinfo to return EINTR */
    395 	{
    396 	test_timeout, my_rt_sigtimedwait, SIGUSR2},
    397 	    /* 3: The handler is not called when the signal is waited for by sigwaitinfo */
    398 	{
    399 	test_masked_matching, my_rt_sigtimedwait, SIGTERM},
    400 	    /* 4: Simultaneous realtime signals are delivered in the order of increasing signal number */
    401 	{
    402 	test_masked_matching_rt, my_rt_sigtimedwait, -1},
    403 #endif
    404 #if defined TEST_SIGWAIT
    405 	{
    406 	test_unmasked_matching_noinfo, my_sigwait, SIGUSR1}, {
    407 	test_masked_matching_noinfo, my_sigwait, SIGUSR1},
    408 #endif
    409 #if defined TEST_SIGWAITINFO
    410 	{
    411 	test_empty_set, my_sigwaitinfo, SIGUSR1}, {
    412 	test_unmasked_matching, my_sigwaitinfo, SIGUSR1}, {
    413 	test_masked_matching, my_sigwaitinfo, SIGUSR1}, {
    414 	test_unmasked_matching_noinfo, my_sigwaitinfo, SIGUSR1}, {
    415 	test_masked_matching_noinfo, my_sigwaitinfo, SIGUSR1}, {
    416 	test_bad_address, my_sigwaitinfo, SIGUSR1}, {
    417 	test_bad_address2, my_sigwaitinfo, SIGUSR1},
    418 #endif
    419 #if defined TEST_SIGTIMEDWAIT
    420 	{
    421 	test_empty_set, my_sigtimedwait, SIGUSR1}, {
    422 	test_unmasked_matching, my_sigtimedwait, SIGUSR1}, {
    423 	test_masked_matching, my_sigtimedwait, SIGUSR1}, {
    424 	test_unmasked_matching_noinfo, my_sigtimedwait, SIGUSR1}, {
    425 	test_masked_matching_noinfo, my_sigtimedwait, SIGUSR1}, {
    426 	test_bad_address, my_sigtimedwait, SIGUSR1}, {
    427 	test_bad_address2, my_sigtimedwait, SIGUSR1}, {
    428 	test_bad_address3, my_sigtimedwait, SIGUSR1}, {
    429 	test_timeout, my_sigtimedwait, 0},
    430 #endif
    431 };
    432 
    433 #if defined TEST_SIGWAITINFO
    434 const char *TCID = "sigwaitinfo01";
    435 #elif defined TEST_RT_SIGTIMEDWAIT
    436 const char *TCID = "rt_sigtimedwait01";
    437 #elif defined TEST_SIGTIMEDWAIT
    438 const char *TCID = "sigtimedwait01";
    439 #elif defined TEST_SIGWAIT
    440 const char *TCID = "sigwait01";
    441 #endif
    442 
    443 int TST_TOTAL = ARRAY_SIZE(tests);
    444 
    445 int main(int argc, char **argv)
    446 {
    447 	unsigned i;
    448 	int lc;
    449 
    450 	tst_parse_opts(argc, argv, NULL, NULL);
    451 
    452 	setup();
    453 
    454 	for (lc = 0; TEST_LOOPING(lc); ++lc) {
    455 		tst_count = 0;
    456 
    457 		for (i = 0; i < ARRAY_SIZE(tests); i++) {
    458 			alarm(10);	/* arrange a 10 second timeout */
    459 			tst_resm(TINFO, "%p, %d", tests[i].swi, tests[i].signo);
    460 			tests[i].tf(tests[i].swi, tests[i].signo);
    461 		}
    462 		alarm(0);
    463 	}
    464 
    465 	cleanup();
    466 	tst_exit();
    467 }
    468