t_poll.c revision 276478
10SN/A/* $NetBSD: t_poll.c,v 1.3 2012/03/18 07:00:52 jruoho Exp $ */ 210159Scoleenp 30SN/A/*- 40SN/A * Copyright (c) 2011 The NetBSD Foundation, Inc. 50SN/A * All rights reserved. 60SN/A * 70SN/A * This code is derived from software contributed to The NetBSD Foundation 80SN/A * by Matthias Scheler. 90SN/A * 100SN/A * Redistribution and use in source and binary forms, with or without 110SN/A * modification, are permitted provided that the following conditions 120SN/A * are met: 130SN/A * 1. Redistributions of source code must retain the above copyright 140SN/A * notice, this list of conditions and the following disclaimer. 150SN/A * 2. Redistributions in binary form must reproduce the above copyright 160SN/A * notice, this list of conditions and the following disclaimer in the 170SN/A * documentation and/or other materials provided with the distribution. 180SN/A * 191472SN/A * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 201472SN/A * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 211472SN/A * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 220SN/A * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 230SN/A * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 240SN/A * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 251879SN/A * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 261879SN/A * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 271879SN/A * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 281879SN/A * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 291879SN/A * POSSIBILITY OF SUCH DAMAGE. 306402Sgoetz */ 311879SN/A 321879SN/A#include <sys/time.h> 333602Scoleenp#include <sys/wait.h> 343602Scoleenp 355646Scoleenp#include <atf-c.h> 365646Scoleenp#include <errno.h> 375646Scoleenp#include <fcntl.h> 385646Scoleenp#include <paths.h> 390SN/A#include <poll.h> 400SN/A#include <stdio.h> 410SN/A#include <signal.h> 420SN/A#include <unistd.h> 430SN/A 440SN/Astatic int desc; 450SN/A 460SN/Astatic void 473602Scoleenpchild1(void) 483602Scoleenp{ 493602Scoleenp struct pollfd pfd; 503698Stwisti 513698Stwisti pfd.fd = desc; 523698Stwisti pfd.events = POLLIN | POLLHUP | POLLOUT; 533698Stwisti 540SN/A (void)poll(&pfd, 1, 2000); 550SN/A (void)printf("child1 exit\n"); 560SN/A} 570SN/A 580SN/Astatic void 590SN/Achild2(void) 600SN/A{ 613534SN/A struct pollfd pfd; 623602Scoleenp 630SN/A pfd.fd = desc; 643602Scoleenp pfd.events = POLLIN | POLLHUP | POLLOUT; 653602Scoleenp 663602Scoleenp (void)sleep(1); 673602Scoleenp (void)poll(&pfd, 1, INFTIM); 683602Scoleenp (void)printf("child2 exit\n"); 693602Scoleenp} 703602Scoleenp 713602Scoleenpstatic void 720SN/Achild3(void) 730SN/A{ 743534SN/A struct pollfd pfd; 753534SN/A 763534SN/A (void)sleep(5); 773534SN/A 783534SN/A pfd.fd = desc; 790SN/A pfd.events = POLLIN | POLLHUP | POLLOUT; 8010885Scoleenp 810SN/A (void)poll(&pfd, 1, INFTIM); 820SN/A (void)printf("child3 exit\n"); 830SN/A} 8410885Scoleenp 8510885ScoleenpATF_TC(poll_3way); 8610885ScoleenpATF_TC_HEAD(poll_3way, tc) 8710885Scoleenp{ 8810885Scoleenp atf_tc_set_md_var(tc, "timeout", "15"); 8910885Scoleenp atf_tc_set_md_var(tc, "descr", 9010885Scoleenp "Check for 3-way collision for descriptor. First child comes " 9110885Scoleenp "and polls on descriptor, second child comes and polls, first " 9210885Scoleenp "child times out and exits, third child comes and polls. When " 930SN/A "the wakeup event happens, the two remaining children should " 940SN/A "both be awaken. (kern/17517)"); 950SN/A} 963602Scoleenp 973534SN/AATF_TC_BODY(poll_3way, tc) 983534SN/A{ 990SN/A int pf[2]; 1000SN/A int status, i; 1010SN/A pid_t pid; 1020SN/A 1030SN/A pipe(pf); 1043602Scoleenp desc = pf[0]; 1053534SN/A 1063602Scoleenp pid = fork(); 1076206Scoleenp ATF_REQUIRE(pid >= 0); 1086206Scoleenp 1096206Scoleenp if (pid == 0) { 1103534SN/A (void)close(pf[1]); 1113602Scoleenp child1(); 1123534SN/A _exit(0); 1133534SN/A /* NOTREACHED */ 1143534SN/A } 1153534SN/A 1163534SN/A pid = fork(); 1170SN/A ATF_REQUIRE(pid >= 0); 1180SN/A 1190SN/A if (pid == 0) { 1200SN/A (void)close(pf[1]); 1210SN/A child2(); 1220SN/A _exit(0); 1230SN/A /* NOTREACHED */ 1240SN/A } 1250SN/A 1260SN/A pid = fork(); 1273818Stwisti ATF_REQUIRE( pid >= 0); 1283818Stwisti 1290SN/A if (pid == 0) { 1300SN/A (void)close(pf[1]); 131726SN/A child3(); 1323602Scoleenp _exit(0); 1333602Scoleenp /* NOTREACHED */ 134726SN/A } 1350SN/A 1360SN/A (void)sleep(10); 1373602Scoleenp 1383602Scoleenp (void)printf("parent write\n"); 1390SN/A 1400SN/A ATF_REQUIRE(write(pf[1], "konec\n", 6) == 6); 1410SN/A 1420SN/A for(i = 0; i < 3; ++i) 1430SN/A (void)wait(&status); 1445997Sgoetz 1453602Scoleenp (void)printf("parent terminated\n"); 1460SN/A} 1473602Scoleenp 1480SN/AATF_TC(poll_basic); 1493602ScoleenpATF_TC_HEAD(poll_basic, tc) 1504980Srbackman{ 1514980Srbackman atf_tc_set_md_var(tc, "timeout", "10"); 1524980Srbackman atf_tc_set_md_var(tc, "descr", 1534980Srbackman "Basis functionality test for poll(2)"); 1544980Srbackman} 1554980Srbackman 1564980SrbackmanATF_TC_BODY(poll_basic, tc) 1574980Srbackman{ 1584980Srbackman int fds[2]; 1593534SN/A struct pollfd pfds[2]; 1600SN/A int ret; 1613534SN/A 1623534SN/A ATF_REQUIRE_EQ(pipe(fds), 0); 1633534SN/A 1643534SN/A pfds[0].fd = fds[0]; 1653534SN/A pfds[0].events = POLLIN; 1663534SN/A pfds[1].fd = fds[1]; 1673534SN/A pfds[1].events = POLLOUT; 1683534SN/A 1693534SN/A /* 1703534SN/A * Check that we get a timeout waiting for data on the read end 1713534SN/A * of our pipe. 1723534SN/A */ 1733534SN/A pfds[0].revents = -1; 1740SN/A pfds[1].revents = -1; 1750SN/A ATF_REQUIRE_EQ_MSG(ret = poll(&pfds[0], 1, 1), 0, 1763534SN/A "got: %d", ret); 1773534SN/A ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents); 1783534SN/A ATF_REQUIRE_EQ_MSG(pfds[1].revents, -1, "got: %d", pfds[1].revents); 1793534SN/A 1803534SN/A /* Check that the write end of the pipe as reported as ready. */ 1813534SN/A pfds[0].revents = -1; 1823534SN/A pfds[1].revents = -1; 1833534SN/A ATF_REQUIRE_EQ_MSG(ret = poll(&pfds[1], 1, 1), 1, 1843602Scoleenp "got: %d", ret); 1853698Stwisti ATF_REQUIRE_EQ_MSG(pfds[0].revents, -1, "got: %d", pfds[0].revents); 1863698Stwisti ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",\ 1873698Stwisti pfds[1].revents); 1883698Stwisti 1893698Stwisti /* Check that only the write end of the pipe as reported as ready. */ 1903698Stwisti pfds[0].revents = -1; 1913534SN/A pfds[1].revents = -1; 1923534SN/A ATF_REQUIRE_EQ_MSG(ret = poll(pfds, 2, 1), 1, 1933534SN/A "got: %d", ret); 1943534SN/A ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents); 1953534SN/A ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d", 19611507Skbarrett pfds[1].revents); 1970SN/A 1980SN/A /* Write data to our pipe. */ 1993534SN/A ATF_REQUIRE_EQ(write(fds[1], "", 1), 1); 2003534SN/A 2013602Scoleenp /* Check that both ends of our pipe are reported as ready. */ 2023602Scoleenp pfds[0].revents = -1; 2033602Scoleenp pfds[1].revents = -1; 2043534SN/A ATF_REQUIRE_EQ_MSG(ret = poll(pfds, 2, 1), 2, 2053602Scoleenp "got: %d", ret); 2063602Scoleenp ATF_REQUIRE_EQ_MSG(pfds[0].revents, POLLIN, "got: %d", 2073534SN/A pfds[0].revents); 2080SN/A ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d", 2090SN/A pfds[1].revents); 2100SN/A 2111059SN/A ATF_REQUIRE_EQ(close(fds[0]), 0); 2123602Scoleenp ATF_REQUIRE_EQ(close(fds[1]), 0); 2133602Scoleenp} 2143602Scoleenp 2153602ScoleenpATF_TC(poll_err); 2160SN/AATF_TC_HEAD(poll_err, tc) 2170SN/A{ 2180SN/A atf_tc_set_md_var(tc, "descr", "Check errors from poll(2)"); 2190SN/A} 2200SN/A 2210SN/AATF_TC_BODY(poll_err, tc) 2220SN/A{ 2230SN/A struct pollfd pfd; 2240SN/A int fd = 0; 2253602Scoleenp 2263602Scoleenp pfd.fd = fd; 2270SN/A pfd.events = POLLIN; 2280SN/A 2295297Sdrchase errno = 0; 2305297Sdrchase ATF_REQUIRE_ERRNO(EFAULT, poll((struct pollfd *)-1, 1, -1) == -1); 2310SN/A 2320SN/A errno = 0; 23312741Scoleenp ATF_REQUIRE_ERRNO(EINVAL, poll(&pfd, 1, -2) == -1); 23412741Scoleenp} 2350SN/A 2360SN/A#ifndef __FreeBSD__ 2375297SdrchaseATF_TC(pollts_basic); 2385297SdrchaseATF_TC_HEAD(pollts_basic, tc) 2395297Sdrchase{ 24012741Scoleenp atf_tc_set_md_var(tc, "timeout", "10"); 24112741Scoleenp atf_tc_set_md_var(tc, "descr", 2425297Sdrchase "Basis functionality test for pollts(2)"); 2435297Sdrchase} 2445297Sdrchase 2455297SdrchaseATF_TC_BODY(pollts_basic, tc) 2465297Sdrchase{ 2475297Sdrchase int fds[2]; 2485297Sdrchase struct pollfd pfds[2]; 2495297Sdrchase struct timespec timeout; 2505297Sdrchase int ret; 2515297Sdrchase 2529248Scoleenp ATF_REQUIRE_EQ(pipe(fds), 0); 2535297Sdrchase 2540SN/A pfds[0].fd = fds[0]; 2550SN/A pfds[0].events = POLLIN; 2563534SN/A pfds[1].fd = fds[1]; 2579248Scoleenp pfds[1].events = POLLOUT; 2583818Stwisti 2593534SN/A /* Use a timeout of 1 second. */ 2603534SN/A timeout.tv_sec = 1; 261726SN/A timeout.tv_nsec = 0; 2629248Scoleenp 2633818Stwisti /* 264726SN/A * Check that we get a timeout waiting for data on the read end 265726SN/A * of our pipe. 2663534SN/A */ 2671580SN/A pfds[0].revents = -1; 2683534SN/A pfds[1].revents = -1; 2693534SN/A ATF_REQUIRE_EQ_MSG(ret = pollts(&pfds[0], 1, &timeout, NULL), 0, 2703534SN/A "got: %d", ret); 2713534SN/A ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents); 2723534SN/A ATF_REQUIRE_EQ_MSG(pfds[1].revents, -1, "got: %d", pfds[1].revents); 2733534SN/A 2743534SN/A /* Check that the write end of the pipe as reported as ready. */ 2753534SN/A pfds[0].revents = -1; 2763534SN/A pfds[1].revents = -1; 2773534SN/A ATF_REQUIRE_EQ_MSG(ret = pollts(&pfds[1], 1, &timeout, NULL), 1, 2783602Scoleenp "got: %d", ret); 2793534SN/A ATF_REQUIRE_EQ_MSG(pfds[0].revents, -1, "got: %d", pfds[0].revents); 2803534SN/A ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",\ 2813534SN/A pfds[1].revents); 2829248Scoleenp 2833534SN/A /* Check that only the write end of the pipe as reported as ready. */ 2843818Stwisti pfds[0].revents = -1; 2853534SN/A pfds[1].revents = -1; 2863534SN/A ATF_REQUIRE_EQ_MSG(ret = pollts(pfds, 2, &timeout, NULL), 1, 2873698Stwisti "got: %d", ret); 2883698Stwisti ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents); 2893698Stwisti ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d", 2903698Stwisti pfds[1].revents); 2913698Stwisti 2923698Stwisti /* Write data to our pipe. */ 2933698Stwisti ATF_REQUIRE_EQ(write(fds[1], "", 1), 1); 2943698Stwisti 2953698Stwisti /* Check that both ends of our pipe are reported as ready. */ 2963698Stwisti pfds[0].revents = -1; 2979248Scoleenp pfds[1].revents = -1; 2989248Scoleenp ATF_REQUIRE_EQ_MSG(ret = pollts(pfds, 2, &timeout, NULL), 2, 2999248Scoleenp "got: %d", ret); 3003534SN/A ATF_REQUIRE_EQ_MSG(pfds[0].revents, POLLIN, "got: %d", 3013534SN/A pfds[0].revents); 3020SN/A ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d", 3030SN/A pfds[1].revents); 3040SN/A 3050SN/A ATF_REQUIRE_EQ(close(fds[0]), 0); 3060SN/A ATF_REQUIRE_EQ(close(fds[1]), 0); 3070SN/A} 3080SN/A 3090SN/AATF_TC(pollts_err); 3100SN/AATF_TC_HEAD(pollts_err, tc) 3113698Stwisti{ 3123698Stwisti atf_tc_set_md_var(tc, "descr", "Check errors from pollts(2)"); 3130SN/A} 3140SN/A 3150SN/AATF_TC_BODY(pollts_err, tc) 3160SN/A{ 3170SN/A struct timespec timeout; 3180SN/A struct pollfd pfd; 3190SN/A int fd = 0; 3200SN/A 3210SN/A pfd.fd = fd; 3220SN/A pfd.events = POLLIN; 3230SN/A 3240SN/A timeout.tv_sec = 1; 3250SN/A timeout.tv_nsec = 0; 3260SN/A 3270SN/A errno = 0; 3280SN/A ATF_REQUIRE_ERRNO(EFAULT, pollts((void *)-1, 1, &timeout, NULL) == -1); 3290SN/A 3300SN/A timeout.tv_sec = -1; 3310SN/A timeout.tv_nsec = -1; 3323602Scoleenp 3335997Sgoetz errno = 0; 3343602Scoleenp ATF_REQUIRE_ERRNO(EINVAL, pollts(&pfd, 1, &timeout, NULL) == -1); 3355997Sgoetz} 3365997Sgoetz 3375997SgoetzATF_TC(pollts_sigmask); 3385997SgoetzATF_TC_HEAD(pollts_sigmask, tc) 3395997Sgoetz{ 3405997Sgoetz atf_tc_set_md_var(tc, "timeout", "10"); 3415997Sgoetz atf_tc_set_md_var(tc, "descr", 3425997Sgoetz "Check that pollts(2) restores the signal mask (PR kern/44986)"); 3435997Sgoetz} 3445997Sgoetz 3455997SgoetzATF_TC_BODY(pollts_sigmask, tc) 3463534SN/A{ 3475997Sgoetz int fd; 3483534SN/A struct pollfd pfd; 3493534SN/A struct timespec timeout; 3503534SN/A sigset_t mask; 3513534SN/A int ret; 3523534SN/A 3533534SN/A fd = open(_PATH_DEVNULL, O_RDONLY); 3546549Sdrchase ATF_REQUIRE(fd >= 0); 3556549Sdrchase 3563534SN/A pfd.fd = fd; 3573534SN/A pfd.events = POLLIN; 3583534SN/A 3593534SN/A /* Use a timeout of 1 second. */ 3603534SN/A timeout.tv_sec = 1; 3613534SN/A timeout.tv_nsec = 0; 3620SN/A 3630SN/A /* Unblock all signals. */ 36412727Saph ATF_REQUIRE_EQ(sigfillset(&mask), 0); 36512727Saph ATF_REQUIRE_EQ(sigprocmask(SIG_UNBLOCK, &mask, NULL), 0); 36612727Saph 3671059SN/A /* 3680SN/A * Check that pollts(2) immediately returns. We block *all* 3690SN/A * signals during pollts(2). 3700SN/A */ 3710SN/A ATF_REQUIRE_EQ_MSG(ret = pollts(&pfd, 1, &timeout, &mask), 1, 3720SN/A "got: %d", ret); 3734127Sdcubed 3740SN/A /* Check that signals are now longer blocked. */ 3754127Sdcubed ATF_REQUIRE_EQ(sigprocmask(SIG_SETMASK, NULL, &mask), 0); 3760SN/A ATF_REQUIRE_EQ_MSG(sigismember(&mask, SIGUSR1), 0, 3770SN/A "signal mask was changed."); 3780SN/A 3790SN/A ATF_REQUIRE_EQ(close(fd), 0); 3803602Scoleenp} 3817914Ssspitsyn#endif 3824127Sdcubed 3837914SsspitsynATF_TP_ADD_TCS(tp) 3844127Sdcubed{ 3850SN/A 3860SN/A ATF_TP_ADD_TC(tp, poll_3way); 3870SN/A ATF_TP_ADD_TC(tp, poll_basic); 3880SN/A ATF_TP_ADD_TC(tp, poll_err); 3890SN/A#ifndef __FreeBSD__ 3903534SN/A ATF_TP_ADD_TC(tp, pollts_basic); 3913534SN/A ATF_TP_ADD_TC(tp, pollts_err); 3923534SN/A ATF_TP_ADD_TC(tp, pollts_sigmask); 3930SN/A#endif 3940SN/A 3950SN/A return atf_no_error(); 3960SN/A} 3970SN/A