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