xref: /freebsd-src/contrib/netbsd-tests/lib/libc/sys/t_select.c (revision 1a36faad54665288ed4eb839d2a4699ae2ead45e)
1*63d1fd59SEnji Cooper /*	$NetBSD: t_select.c,v 1.4 2017/01/13 21:18:33 christos Exp $ */
257718be8SEnji Cooper 
357718be8SEnji Cooper /*-
457718be8SEnji Cooper  * Copyright (c) 2011 The NetBSD Foundation, Inc.
557718be8SEnji Cooper  * All rights reserved.
657718be8SEnji Cooper  *
757718be8SEnji Cooper  * This code is derived from software contributed to The NetBSD Foundatiom
857718be8SEnji Cooper  * by Christos Zoulas.
957718be8SEnji Cooper  *
1057718be8SEnji Cooper  * Redistribution and use in source and binary forms, with or without
1157718be8SEnji Cooper  * modification, are permitted provided that the following conditions
1257718be8SEnji Cooper  * are met:
1357718be8SEnji Cooper  * 1. Redistributions of source code must retain the above copyright
1457718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer.
1557718be8SEnji Cooper  * 2. Redistributions in binary form must reproduce the above copyright
1657718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer in the
1757718be8SEnji Cooper  *    documentation and/or other materials provided with the distribution.
1857718be8SEnji Cooper  *
1957718be8SEnji Cooper  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2057718be8SEnji Cooper  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2157718be8SEnji Cooper  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2257718be8SEnji Cooper  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2357718be8SEnji Cooper  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2457718be8SEnji Cooper  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2557718be8SEnji Cooper  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2657718be8SEnji Cooper  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2757718be8SEnji Cooper  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2857718be8SEnji Cooper  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2957718be8SEnji Cooper  * POSSIBILITY OF SUCH DAMAGE.
3057718be8SEnji Cooper  */
3157718be8SEnji Cooper 
3257718be8SEnji Cooper #include <assert.h>
3357718be8SEnji Cooper #include <sys/types.h>
3457718be8SEnji Cooper #include <sys/select.h>
3557718be8SEnji Cooper #include <sys/wait.h>
3657718be8SEnji Cooper #include <err.h>
3757718be8SEnji Cooper #include <stdio.h>
3857718be8SEnji Cooper #include <string.h>
3957718be8SEnji Cooper #include <signal.h>
4057718be8SEnji Cooper #include <stdlib.h>
4157718be8SEnji Cooper #include <unistd.h>
4257718be8SEnji Cooper #include <errno.h>
4357718be8SEnji Cooper #include <fcntl.h>
4457718be8SEnji Cooper 
4557718be8SEnji Cooper #include <atf-c.h>
4657718be8SEnji Cooper 
4757718be8SEnji Cooper static sig_atomic_t keep_going = 1;
4857718be8SEnji Cooper 
4957718be8SEnji Cooper static void
sig_handler(int signum __unused)50eef4a699SEnji Cooper sig_handler(int signum __unused)
5157718be8SEnji Cooper {
5257718be8SEnji Cooper 	keep_going = 0;
5357718be8SEnji Cooper }
5457718be8SEnji Cooper 
5557718be8SEnji Cooper static void
sigchld(int signum __unused)56eef4a699SEnji Cooper sigchld(int signum __unused)
5757718be8SEnji Cooper {
5857718be8SEnji Cooper }
5957718be8SEnji Cooper 
6057718be8SEnji Cooper static char
xtoa(uint8_t n)6157718be8SEnji Cooper xtoa(uint8_t n)
6257718be8SEnji Cooper {
6357718be8SEnji Cooper 	static const char xarray[] = "0123456789abcdef";
6457718be8SEnji Cooper 	assert(n < sizeof(xarray));
6557718be8SEnji Cooper 	return xarray[n];
6657718be8SEnji Cooper }
6757718be8SEnji Cooper 
6857718be8SEnji Cooper static const char *
prmask(const sigset_t * m,char * buf,size_t len)6957718be8SEnji Cooper prmask(const sigset_t *m, char *buf, size_t len)
7057718be8SEnji Cooper {
7157718be8SEnji Cooper 	size_t j = 2;
7257718be8SEnji Cooper 	assert(len >= 3 + sizeof(*m));
7357718be8SEnji Cooper 	buf[0] = '0';
7457718be8SEnji Cooper 	buf[1] = 'x';
7557718be8SEnji Cooper #define N(p, a)	(((p) >> ((a) * 4)) & 0xf)
7657718be8SEnji Cooper 	for (size_t i = __arraycount(m->__bits); i > 0; i--) {
7757718be8SEnji Cooper 		uint32_t p = m->__bits[i - 1];
7857718be8SEnji Cooper 		for (size_t k = sizeof(p); k > 0; k--)
7957718be8SEnji Cooper 			buf[j++] = xtoa(N(p, k - 1));
8057718be8SEnji Cooper 	}
8157718be8SEnji Cooper 	buf[j] = '\0';
8257718be8SEnji Cooper 	return buf;
8357718be8SEnji Cooper }
8457718be8SEnji Cooper 
85*63d1fd59SEnji Cooper static __dead void
child(const struct timespec * ts)8657718be8SEnji Cooper child(const struct timespec *ts)
8757718be8SEnji Cooper {
8857718be8SEnji Cooper 	struct sigaction sa;
8957718be8SEnji Cooper 	sigset_t set, oset, nset;
9057718be8SEnji Cooper 	char obuf[sizeof(oset) + 3], nbuf[sizeof(nset) + 3];
9157718be8SEnji Cooper 	int fd;
9257718be8SEnji Cooper 
9357718be8SEnji Cooper 	memset(&sa, 0, sizeof(sa));
9457718be8SEnji Cooper 	sa.sa_handler = sig_handler;
9557718be8SEnji Cooper 	if ((fd = open("/dev/null", O_RDONLY)) == -1)
9657718be8SEnji Cooper 		err(1, "open");
9757718be8SEnji Cooper 
9857718be8SEnji Cooper 	if (sigaction(SIGTERM, &sa, NULL) == -1)
9957718be8SEnji Cooper 		err(1, "sigaction");
10057718be8SEnji Cooper 
10157718be8SEnji Cooper 	sigfillset(&set);
10257718be8SEnji Cooper 	if (sigprocmask(SIG_BLOCK, &set, NULL) == -1)
10357718be8SEnji Cooper 		err(1, "sigprocmask");
10457718be8SEnji Cooper 
10557718be8SEnji Cooper 	if (sigprocmask(SIG_BLOCK, NULL, &oset) == -1)
10657718be8SEnji Cooper 		err(1, "sigprocmask");
10757718be8SEnji Cooper 
10857718be8SEnji Cooper 	sigemptyset(&set);
10957718be8SEnji Cooper 
11057718be8SEnji Cooper 	for (;;) {
11157718be8SEnji Cooper 		fd_set rset;
11257718be8SEnji Cooper 		FD_ZERO(&rset);
11357718be8SEnji Cooper 		FD_SET(fd, &rset);
11457718be8SEnji Cooper 		if (pselect(1, &rset, NULL, NULL, ts, &set) == -1) {
11557718be8SEnji Cooper 			if(errno == EINTR) {
11657718be8SEnji Cooper 				if (!keep_going)
11757718be8SEnji Cooper 					break;
11857718be8SEnji Cooper 			}
11957718be8SEnji Cooper 		}
12057718be8SEnji Cooper 		if (ts)
12157718be8SEnji Cooper 			break;
12257718be8SEnji Cooper 	}
12357718be8SEnji Cooper 	if (sigprocmask(SIG_BLOCK, NULL, &nset) == -1)
12457718be8SEnji Cooper 		err(1, "sigprocmask");
12557718be8SEnji Cooper 	if (memcmp(&oset, &nset, sizeof(oset)) != 0)
12657718be8SEnji Cooper 		atf_tc_fail("pselect() masks don't match "
12757718be8SEnji Cooper 		    "after timeout %s != %s",
12857718be8SEnji Cooper 		    prmask(&nset, nbuf, sizeof(nbuf)),
12957718be8SEnji Cooper 		    prmask(&oset, obuf, sizeof(obuf)));
1307251167fSEnji Cooper 	_exit(0);
13157718be8SEnji Cooper }
13257718be8SEnji Cooper 
13357718be8SEnji Cooper ATF_TC(pselect_sigmask);
ATF_TC_HEAD(pselect_sigmask,tc)13457718be8SEnji Cooper ATF_TC_HEAD(pselect_sigmask, tc)
13557718be8SEnji Cooper {
13657718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks pselect's temporary mask "
13757718be8SEnji Cooper 	    "setting when a signal is received (PR lib/43625)");
13857718be8SEnji Cooper }
13957718be8SEnji Cooper 
ATF_TC_BODY(pselect_sigmask,tc)14057718be8SEnji Cooper ATF_TC_BODY(pselect_sigmask, tc)
14157718be8SEnji Cooper {
14257718be8SEnji Cooper 	pid_t pid;
14357718be8SEnji Cooper 	int status;
14457718be8SEnji Cooper 
14557718be8SEnji Cooper 	signal(SIGCHLD, sigchld);
14657718be8SEnji Cooper 
14757718be8SEnji Cooper 	switch (pid = fork()) {
14857718be8SEnji Cooper 	case 0:
14957718be8SEnji Cooper 		child(NULL);
150*63d1fd59SEnji Cooper 		/*NOTREACHED*/
15157718be8SEnji Cooper 	case -1:
15257718be8SEnji Cooper 		err(1, "fork");
15357718be8SEnji Cooper 	default:
15457718be8SEnji Cooper 		sleep(1);
15557718be8SEnji Cooper 		if (kill(pid, SIGTERM) == -1)
15657718be8SEnji Cooper 			err(1, "kill");
15757718be8SEnji Cooper 		sleep(1);
15857718be8SEnji Cooper 		switch (waitpid(pid, &status, WNOHANG)) {
15957718be8SEnji Cooper 		case -1:
16057718be8SEnji Cooper 			err(1, "wait");
16157718be8SEnji Cooper 		case 0:
16257718be8SEnji Cooper 			if (kill(pid, SIGKILL) == -1)
16357718be8SEnji Cooper 				err(1, "kill");
16457718be8SEnji Cooper 			atf_tc_fail("pselect() did not receive signal");
16557718be8SEnji Cooper 			break;
16657718be8SEnji Cooper 		default:
16757718be8SEnji Cooper 			break;
16857718be8SEnji Cooper 		}
16957718be8SEnji Cooper 	}
17057718be8SEnji Cooper }
17157718be8SEnji Cooper 
17257718be8SEnji Cooper ATF_TC(pselect_timeout);
ATF_TC_HEAD(pselect_timeout,tc)17357718be8SEnji Cooper ATF_TC_HEAD(pselect_timeout, tc)
17457718be8SEnji Cooper {
17557718be8SEnji Cooper 
17657718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks pselect's temporary mask "
17757718be8SEnji Cooper 	    "setting when a timeout occurs");
17857718be8SEnji Cooper }
17957718be8SEnji Cooper 
ATF_TC_BODY(pselect_timeout,tc)18057718be8SEnji Cooper ATF_TC_BODY(pselect_timeout, tc)
18157718be8SEnji Cooper {
18257718be8SEnji Cooper 	pid_t pid;
18357718be8SEnji Cooper 	int status;
18457718be8SEnji Cooper 	static const struct timespec zero = { 0, 0 };
18557718be8SEnji Cooper 
18657718be8SEnji Cooper 	signal(SIGCHLD, sigchld);
18757718be8SEnji Cooper 
18857718be8SEnji Cooper 	switch (pid = fork()) {
18957718be8SEnji Cooper 	case 0:
19057718be8SEnji Cooper 		child(&zero);
19157718be8SEnji Cooper 		break;
19257718be8SEnji Cooper 	case -1:
19357718be8SEnji Cooper 		err(1, "fork");
19457718be8SEnji Cooper 	default:
19557718be8SEnji Cooper 		sleep(1);
19657718be8SEnji Cooper 		switch (waitpid(pid, &status, WNOHANG)) {
19757718be8SEnji Cooper 		case -1:
19857718be8SEnji Cooper 			err(1, "wait");
19957718be8SEnji Cooper 		case 0:
20057718be8SEnji Cooper 			if (kill(pid, SIGKILL) == -1)
20157718be8SEnji Cooper 				err(1, "kill");
20257718be8SEnji Cooper 			atf_tc_fail("pselect() did not receive signal");
20357718be8SEnji Cooper 			break;
20457718be8SEnji Cooper 		default:
20557718be8SEnji Cooper 			break;
20657718be8SEnji Cooper 		}
20757718be8SEnji Cooper 	}
20857718be8SEnji Cooper }
20957718be8SEnji Cooper 
ATF_TP_ADD_TCS(tp)21057718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
21157718be8SEnji Cooper {
21257718be8SEnji Cooper 
21357718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, pselect_sigmask);
21457718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, pselect_timeout);
21557718be8SEnji Cooper 
21657718be8SEnji Cooper 	return atf_no_error();
21757718be8SEnji Cooper }
218