1*57718be8SEnji Cooper /* $NetBSD: t_select.c,v 1.3 2012/03/18 07:00:52 jruoho Exp $ */ 2*57718be8SEnji Cooper 3*57718be8SEnji Cooper /*- 4*57718be8SEnji Cooper * Copyright (c) 2011 The NetBSD Foundation, Inc. 5*57718be8SEnji Cooper * All rights reserved. 6*57718be8SEnji Cooper * 7*57718be8SEnji Cooper * This code is derived from software contributed to The NetBSD Foundatiom 8*57718be8SEnji Cooper * by Christos Zoulas. 9*57718be8SEnji Cooper * 10*57718be8SEnji Cooper * Redistribution and use in source and binary forms, with or without 11*57718be8SEnji Cooper * modification, are permitted provided that the following conditions 12*57718be8SEnji Cooper * are met: 13*57718be8SEnji Cooper * 1. Redistributions of source code must retain the above copyright 14*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer. 15*57718be8SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 16*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer in the 17*57718be8SEnji Cooper * documentation and/or other materials provided with the distribution. 18*57718be8SEnji Cooper * 19*57718be8SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20*57718be8SEnji Cooper * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21*57718be8SEnji Cooper * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22*57718be8SEnji Cooper * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23*57718be8SEnji Cooper * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24*57718be8SEnji Cooper * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25*57718be8SEnji Cooper * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26*57718be8SEnji Cooper * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27*57718be8SEnji Cooper * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28*57718be8SEnji Cooper * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29*57718be8SEnji Cooper * POSSIBILITY OF SUCH DAMAGE. 30*57718be8SEnji Cooper */ 31*57718be8SEnji Cooper 32*57718be8SEnji Cooper #include <assert.h> 33*57718be8SEnji Cooper #include <sys/types.h> 34*57718be8SEnji Cooper #include <sys/select.h> 35*57718be8SEnji Cooper #include <sys/wait.h> 36*57718be8SEnji Cooper #include <err.h> 37*57718be8SEnji Cooper #include <stdio.h> 38*57718be8SEnji Cooper #include <string.h> 39*57718be8SEnji Cooper #include <signal.h> 40*57718be8SEnji Cooper #include <stdlib.h> 41*57718be8SEnji Cooper #include <unistd.h> 42*57718be8SEnji Cooper #include <errno.h> 43*57718be8SEnji Cooper #include <fcntl.h> 44*57718be8SEnji Cooper 45*57718be8SEnji Cooper #include <atf-c.h> 46*57718be8SEnji Cooper 47*57718be8SEnji Cooper static sig_atomic_t keep_going = 1; 48*57718be8SEnji Cooper 49*57718be8SEnji Cooper static void 50*57718be8SEnji Cooper sig_handler(int signum) 51*57718be8SEnji Cooper { 52*57718be8SEnji Cooper keep_going = 0; 53*57718be8SEnji Cooper } 54*57718be8SEnji Cooper 55*57718be8SEnji Cooper static void 56*57718be8SEnji Cooper sigchld(int signum) 57*57718be8SEnji Cooper { 58*57718be8SEnji Cooper } 59*57718be8SEnji Cooper 60*57718be8SEnji Cooper static char 61*57718be8SEnji Cooper xtoa(uint8_t n) 62*57718be8SEnji Cooper { 63*57718be8SEnji Cooper static const char xarray[] = "0123456789abcdef"; 64*57718be8SEnji Cooper assert(n < sizeof(xarray)); 65*57718be8SEnji Cooper return xarray[n]; 66*57718be8SEnji Cooper } 67*57718be8SEnji Cooper 68*57718be8SEnji Cooper static const char * 69*57718be8SEnji Cooper prmask(const sigset_t *m, char *buf, size_t len) 70*57718be8SEnji Cooper { 71*57718be8SEnji Cooper size_t j = 2; 72*57718be8SEnji Cooper assert(len >= 3 + sizeof(*m)); 73*57718be8SEnji Cooper buf[0] = '0'; 74*57718be8SEnji Cooper buf[1] = 'x'; 75*57718be8SEnji Cooper #define N(p, a) (((p) >> ((a) * 4)) & 0xf) 76*57718be8SEnji Cooper for (size_t i = __arraycount(m->__bits); i > 0; i--) { 77*57718be8SEnji Cooper uint32_t p = m->__bits[i - 1]; 78*57718be8SEnji Cooper for (size_t k = sizeof(p); k > 0; k--) 79*57718be8SEnji Cooper buf[j++] = xtoa(N(p, k - 1)); 80*57718be8SEnji Cooper } 81*57718be8SEnji Cooper buf[j] = '\0'; 82*57718be8SEnji Cooper return buf; 83*57718be8SEnji Cooper } 84*57718be8SEnji Cooper 85*57718be8SEnji Cooper static void 86*57718be8SEnji Cooper child(const struct timespec *ts) 87*57718be8SEnji Cooper { 88*57718be8SEnji Cooper struct sigaction sa; 89*57718be8SEnji Cooper sigset_t set, oset, nset; 90*57718be8SEnji Cooper char obuf[sizeof(oset) + 3], nbuf[sizeof(nset) + 3]; 91*57718be8SEnji Cooper int fd; 92*57718be8SEnji Cooper 93*57718be8SEnji Cooper memset(&sa, 0, sizeof(sa)); 94*57718be8SEnji Cooper sa.sa_handler = sig_handler; 95*57718be8SEnji Cooper if ((fd = open("/dev/null", O_RDONLY)) == -1) 96*57718be8SEnji Cooper err(1, "open"); 97*57718be8SEnji Cooper 98*57718be8SEnji Cooper if (sigaction(SIGTERM, &sa, NULL) == -1) 99*57718be8SEnji Cooper err(1, "sigaction"); 100*57718be8SEnji Cooper 101*57718be8SEnji Cooper sigfillset(&set); 102*57718be8SEnji Cooper if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) 103*57718be8SEnji Cooper err(1, "sigprocmask"); 104*57718be8SEnji Cooper 105*57718be8SEnji Cooper if (sigprocmask(SIG_BLOCK, NULL, &oset) == -1) 106*57718be8SEnji Cooper err(1, "sigprocmask"); 107*57718be8SEnji Cooper 108*57718be8SEnji Cooper sigemptyset(&set); 109*57718be8SEnji Cooper 110*57718be8SEnji Cooper for (;;) { 111*57718be8SEnji Cooper fd_set rset; 112*57718be8SEnji Cooper FD_ZERO(&rset); 113*57718be8SEnji Cooper FD_SET(fd, &rset); 114*57718be8SEnji Cooper if (pselect(1, &rset, NULL, NULL, ts, &set) == -1) { 115*57718be8SEnji Cooper if(errno == EINTR) { 116*57718be8SEnji Cooper if (!keep_going) 117*57718be8SEnji Cooper break; 118*57718be8SEnji Cooper } 119*57718be8SEnji Cooper } 120*57718be8SEnji Cooper if (ts) 121*57718be8SEnji Cooper break; 122*57718be8SEnji Cooper } 123*57718be8SEnji Cooper if (sigprocmask(SIG_BLOCK, NULL, &nset) == -1) 124*57718be8SEnji Cooper err(1, "sigprocmask"); 125*57718be8SEnji Cooper if (memcmp(&oset, &nset, sizeof(oset)) != 0) 126*57718be8SEnji Cooper atf_tc_fail("pselect() masks don't match " 127*57718be8SEnji Cooper "after timeout %s != %s", 128*57718be8SEnji Cooper prmask(&nset, nbuf, sizeof(nbuf)), 129*57718be8SEnji Cooper prmask(&oset, obuf, sizeof(obuf))); 130*57718be8SEnji Cooper } 131*57718be8SEnji Cooper 132*57718be8SEnji Cooper ATF_TC(pselect_sigmask); 133*57718be8SEnji Cooper ATF_TC_HEAD(pselect_sigmask, tc) 134*57718be8SEnji Cooper { 135*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Checks pselect's temporary mask " 136*57718be8SEnji Cooper "setting when a signal is received (PR lib/43625)"); 137*57718be8SEnji Cooper } 138*57718be8SEnji Cooper 139*57718be8SEnji Cooper ATF_TC_BODY(pselect_sigmask, tc) 140*57718be8SEnji Cooper { 141*57718be8SEnji Cooper pid_t pid; 142*57718be8SEnji Cooper int status; 143*57718be8SEnji Cooper 144*57718be8SEnji Cooper signal(SIGCHLD, sigchld); 145*57718be8SEnji Cooper 146*57718be8SEnji Cooper switch (pid = fork()) { 147*57718be8SEnji Cooper case 0: 148*57718be8SEnji Cooper child(NULL); 149*57718be8SEnji Cooper case -1: 150*57718be8SEnji Cooper err(1, "fork"); 151*57718be8SEnji Cooper default: 152*57718be8SEnji Cooper sleep(1); 153*57718be8SEnji Cooper if (kill(pid, SIGTERM) == -1) 154*57718be8SEnji Cooper err(1, "kill"); 155*57718be8SEnji Cooper sleep(1); 156*57718be8SEnji Cooper switch (waitpid(pid, &status, WNOHANG)) { 157*57718be8SEnji Cooper case -1: 158*57718be8SEnji Cooper err(1, "wait"); 159*57718be8SEnji Cooper case 0: 160*57718be8SEnji Cooper if (kill(pid, SIGKILL) == -1) 161*57718be8SEnji Cooper err(1, "kill"); 162*57718be8SEnji Cooper atf_tc_fail("pselect() did not receive signal"); 163*57718be8SEnji Cooper break; 164*57718be8SEnji Cooper default: 165*57718be8SEnji Cooper break; 166*57718be8SEnji Cooper } 167*57718be8SEnji Cooper } 168*57718be8SEnji Cooper } 169*57718be8SEnji Cooper 170*57718be8SEnji Cooper ATF_TC(pselect_timeout); 171*57718be8SEnji Cooper ATF_TC_HEAD(pselect_timeout, tc) 172*57718be8SEnji Cooper { 173*57718be8SEnji Cooper 174*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Checks pselect's temporary mask " 175*57718be8SEnji Cooper "setting when a timeout occurs"); 176*57718be8SEnji Cooper } 177*57718be8SEnji Cooper 178*57718be8SEnji Cooper ATF_TC_BODY(pselect_timeout, tc) 179*57718be8SEnji Cooper { 180*57718be8SEnji Cooper pid_t pid; 181*57718be8SEnji Cooper int status; 182*57718be8SEnji Cooper static const struct timespec zero = { 0, 0 }; 183*57718be8SEnji Cooper 184*57718be8SEnji Cooper signal(SIGCHLD, sigchld); 185*57718be8SEnji Cooper 186*57718be8SEnji Cooper switch (pid = fork()) { 187*57718be8SEnji Cooper case 0: 188*57718be8SEnji Cooper child(&zero); 189*57718be8SEnji Cooper break; 190*57718be8SEnji Cooper case -1: 191*57718be8SEnji Cooper err(1, "fork"); 192*57718be8SEnji Cooper default: 193*57718be8SEnji Cooper sleep(1); 194*57718be8SEnji Cooper switch (waitpid(pid, &status, WNOHANG)) { 195*57718be8SEnji Cooper case -1: 196*57718be8SEnji Cooper err(1, "wait"); 197*57718be8SEnji Cooper case 0: 198*57718be8SEnji Cooper if (kill(pid, SIGKILL) == -1) 199*57718be8SEnji Cooper err(1, "kill"); 200*57718be8SEnji Cooper atf_tc_fail("pselect() did not receive signal"); 201*57718be8SEnji Cooper break; 202*57718be8SEnji Cooper default: 203*57718be8SEnji Cooper break; 204*57718be8SEnji Cooper } 205*57718be8SEnji Cooper } 206*57718be8SEnji Cooper } 207*57718be8SEnji Cooper 208*57718be8SEnji Cooper ATF_TP_ADD_TCS(tp) 209*57718be8SEnji Cooper { 210*57718be8SEnji Cooper 211*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, pselect_sigmask); 212*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, pselect_timeout); 213*57718be8SEnji Cooper 214*57718be8SEnji Cooper return atf_no_error(); 215*57718be8SEnji Cooper } 216