Home | History | Annotate | Line # | Download | only in sys
t_poll.c revision 1.10
      1 /*	$NetBSD: t_poll.c,v 1.10 2025/02/09 17:10:23 riastradh Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2011 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Matthias Scheler.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/stat.h>
     33 #include <sys/time.h>
     34 #include <sys/wait.h>
     35 
     36 #include <atf-c.h>
     37 #include <errno.h>
     38 #include <fcntl.h>
     39 #include <paths.h>
     40 #include <poll.h>
     41 #include <stdio.h>
     42 #include <stdlib.h>
     43 #include <signal.h>
     44 #include <unistd.h>
     45 
     46 static int desc;
     47 
     48 static void
     49 child1(void)
     50 {
     51 	struct pollfd pfd;
     52 
     53 	pfd.fd = desc;
     54 	pfd.events = POLLIN | POLLHUP | POLLOUT;
     55 
     56 	(void)poll(&pfd, 1, 2000);
     57 	(void)printf("child1 exit\n");
     58 }
     59 
     60 static void
     61 child2(void)
     62 {
     63 	struct pollfd pfd;
     64 
     65 	pfd.fd = desc;
     66 	pfd.events = POLLIN | POLLHUP | POLLOUT;
     67 
     68 	(void)sleep(1);
     69 	(void)poll(&pfd, 1, INFTIM);
     70 	(void)printf("child2 exit\n");
     71 }
     72 
     73 static void
     74 child3(void)
     75 {
     76 	struct pollfd pfd;
     77 
     78 	(void)sleep(5);
     79 
     80 	pfd.fd = desc;
     81 	pfd.events = POLLIN | POLLHUP | POLLOUT;
     82 
     83 	(void)poll(&pfd, 1, INFTIM);
     84 	(void)printf("child3 exit\n");
     85 }
     86 
     87 ATF_TC(3way);
     88 ATF_TC_HEAD(3way, tc)
     89 {
     90 	atf_tc_set_md_var(tc, "timeout", "15");
     91 	atf_tc_set_md_var(tc, "descr",
     92 	    "Check for 3-way collision for descriptor. First child comes "
     93 	    "and polls on descriptor, second child comes and polls, first "
     94 	    "child times out and exits, third child comes and polls. When "
     95 	    "the wakeup event happens, the two remaining children should "
     96 	    "both be awaken. (kern/17517)");
     97 }
     98 
     99 ATF_TC_BODY(3way, tc)
    100 {
    101 	int pf[2];
    102 	int status, i;
    103 	pid_t pid;
    104 	ssize_t nwrit;
    105 
    106 	RL(pipe(pf));
    107 	desc = pf[0];
    108 
    109 	RL(pid = fork());
    110 	if (pid == 0) {
    111 		if (close(pf[1]) == -1)
    112 			_exit(1);
    113 		child1();
    114 		_exit(0);
    115 		/* NOTREACHED */
    116 	}
    117 
    118 	RL(pid = fork());
    119 	if (pid == 0) {
    120 		if (close(pf[1]) == -1)
    121 			_exit(1);
    122 		child2();
    123 		_exit(0);
    124 		/* NOTREACHED */
    125 	}
    126 
    127 	RL(pid = fork());
    128 	if (pid == 0) {
    129 		if (close(pf[1]) == -1)
    130 			_exit(1);
    131 		child3();
    132 		_exit(0);
    133 		/* NOTREACHED */
    134 	}
    135 
    136 	(void)sleep(10);
    137 
    138 	(void)printf("parent write\n");
    139 
    140 	RL(nwrit = write(pf[1], "konec\n", 6));
    141 	ATF_REQUIRE_EQ_MSG(nwrit, 6, "nwrit=%zd", nwrit);
    142 
    143 	for (i = 0; i < 3; i++)
    144 		RL(wait(&status));
    145 
    146 	(void)printf("parent terminated\n");
    147 }
    148 
    149 ATF_TC(basic);
    150 ATF_TC_HEAD(basic, tc)
    151 {
    152 	atf_tc_set_md_var(tc, "timeout", "10");
    153 	atf_tc_set_md_var(tc, "descr",
    154 	    "Basis functionality test for poll(2)");
    155 }
    156 
    157 ATF_TC_BODY(basic, tc)
    158 {
    159 	int fds[2];
    160 	struct pollfd pfds[2];
    161 	int ret;
    162 	ssize_t nwrit;
    163 
    164 	RL(pipe(fds));
    165 
    166 	pfds[0].fd = fds[0];
    167 	pfds[0].events = POLLIN;
    168 	pfds[1].fd = fds[1];
    169 	pfds[1].events = POLLOUT;
    170 
    171 	/*
    172 	 * Check that we get a timeout waiting for data on the read end
    173 	 * of our pipe.
    174 	 */
    175 	pfds[0].revents = -1;
    176 	pfds[1].revents = -1;
    177 	RL(ret = poll(&pfds[0], 1, 1));
    178 	ATF_REQUIRE_EQ_MSG(ret, 0, "got: %d", ret);
    179 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
    180 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, -1, "got: %d", pfds[1].revents);
    181 
    182 	/* Check that the write end of the pipe as reported as ready. */
    183 	pfds[0].revents = -1;
    184 	pfds[1].revents = -1;
    185 	RL(ret = poll(&pfds[1], 1, 1));
    186 	ATF_REQUIRE_EQ_MSG(ret, 1, "got: %d", ret);
    187 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, -1, "got: %d", pfds[0].revents);
    188 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",\
    189 	    pfds[1].revents);
    190 
    191 	/* Check that only the write end of the pipe as reported as ready. */
    192 	pfds[0].revents = -1;
    193 	pfds[1].revents = -1;
    194 	RL(ret = poll(pfds, 2, 1));
    195 	ATF_REQUIRE_EQ_MSG(ret, 1, "got: %d", ret);
    196 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
    197 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
    198 	    pfds[1].revents);
    199 
    200 	/* Write data to our pipe. */
    201 	RL(nwrit = write(fds[1], "", 1));
    202 	ATF_REQUIRE_EQ_MSG(nwrit, 1, "nwrit=%zd", nwrit);
    203 
    204 	/* Check that both ends of our pipe are reported as ready. */
    205 	pfds[0].revents = -1;
    206 	pfds[1].revents = -1;
    207 	RL(ret = poll(pfds, 2, 1));
    208 	ATF_REQUIRE_EQ_MSG(ret, 2, "got: %d", ret);
    209 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, POLLIN, "got: %d",
    210 	    pfds[0].revents);
    211 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
    212 	    pfds[1].revents);
    213 
    214 	RL(close(fds[0]));
    215 	RL(close(fds[1]));
    216 }
    217 
    218 ATF_TC(err);
    219 ATF_TC_HEAD(err, tc)
    220 {
    221 	atf_tc_set_md_var(tc, "descr", "Check errors from poll(2)");
    222 }
    223 
    224 ATF_TC_BODY(err, tc)
    225 {
    226 	struct pollfd pfd;
    227 	int fd = 0;
    228 
    229 	pfd.fd = fd;
    230 	pfd.events = POLLIN;
    231 
    232 	errno = 0;
    233 	ATF_REQUIRE_ERRNO(EFAULT, poll((struct pollfd *)-1, 1, -1) == -1);
    234 
    235 	errno = 0;
    236 	ATF_REQUIRE_ERRNO(EINVAL, poll(&pfd, 1, -2) == -1);
    237 }
    238 
    239 static const char	fifo_path[] = "pollhup_fifo";
    240 
    241 static void
    242 fifo_support(void)
    243 {
    244 
    245 	errno = 0;
    246 	if (mkfifo(fifo_path, 0600) == 0) {
    247 		RL(unlink(fifo_path));
    248 		return;
    249 	}
    250 
    251 	if (errno == EOPNOTSUPP) {
    252 		atf_tc_skip("the kernel does not support FIFOs");
    253 	} else {
    254 		atf_tc_fail("mkfifo(2) failed");
    255 	}
    256 }
    257 
    258 ATF_TC_WITH_CLEANUP(fifo_inout);
    259 ATF_TC_HEAD(fifo_inout, tc)
    260 {
    261 	atf_tc_set_md_var(tc, "descr",
    262 	    "Check POLLIN/POLLOUT behavior with fifos");
    263 }
    264 
    265 ATF_TC_BODY(fifo_inout, tc)
    266 {
    267 	struct pollfd pfd[2];
    268 	char *buf;
    269 	int rfd, wfd;
    270 	long pipe_buf;
    271 	int ret;
    272 	ssize_t nwrit, nread;
    273 
    274 	fifo_support();
    275 
    276 	RL(mkfifo(fifo_path, 0600));
    277 	RL(rfd = open(fifo_path, O_RDONLY | O_NONBLOCK));
    278 	RL(wfd = open(fifo_path, O_WRONLY | O_NONBLOCK));
    279 
    280 	/* Get the maximum atomic pipe write size. */
    281 	pipe_buf = fpathconf(wfd, _PC_PIPE_BUF);
    282 	ATF_REQUIRE_MSG(pipe_buf > 1, "pipe_buf=%ld", pipe_buf);
    283 
    284 	REQUIRE_LIBC(buf = malloc(pipe_buf), NULL);
    285 
    286 	memset(&pfd, 0, sizeof(pfd));
    287 	pfd[0].fd = rfd;
    288 	pfd[0].events = POLLIN | POLLRDNORM;
    289 	pfd[1].fd = wfd;
    290 	pfd[1].events = POLLOUT | POLLWRNORM;
    291 
    292 	/* We expect the FIFO to be writable but not readable. */
    293 	RL(ret = poll(pfd, 2, 0));
    294 	ATF_REQUIRE_EQ_MSG(ret, 1, "got: %d", ret);
    295 	ATF_REQUIRE_EQ_MSG(pfd[0].revents, 0,
    296 	    "pfd[0].revents=0x%x", pfd[0].revents);
    297 	ATF_REQUIRE_EQ_MSG(pfd[1].revents, POLLOUT|POLLWRNORM,
    298 	    "pfd[1].revents=0x%x", pfd[1].revents);
    299 
    300 	/* Write a single byte of data into the FIFO. */
    301 	RL(nwrit = write(wfd, buf, 1));
    302 	ATF_REQUIRE_EQ_MSG(nwrit, 1, "nwrit=%zd", nwrit);
    303 
    304 	/* We expect the FIFO to be readable and writable. */
    305 	RL(ret = poll(pfd, 2, 0));
    306 	ATF_REQUIRE_EQ_MSG(ret, 2, "got: %d", ret);
    307 	ATF_REQUIRE_EQ_MSG(pfd[0].revents, POLLIN|POLLRDNORM,
    308 	    "pfd[0].revents=0x%x", pfd[0].revents);
    309 	ATF_REQUIRE_EQ_MSG(pfd[1].revents, POLLOUT|POLLWRNORM,
    310 	    "pfd[1].revents=0x%x", pfd[1].revents);
    311 
    312 	/* Read that single byte back out. */
    313 	RL(nread = read(rfd, buf, 1));
    314 	ATF_REQUIRE_EQ_MSG(nread, 1, "nread=%zd", nread);
    315 
    316 	/*
    317 	 * Write data into the FIFO until it is full, which is
    318 	 * defined as insufficient buffer space to hold a the
    319 	 * maximum atomic pipe write size.
    320 	 */
    321 	while (write(wfd, buf, pipe_buf) != -1) {
    322 		continue;
    323 	}
    324 	ATF_REQUIRE_EQ_MSG(errno, EAGAIN, "errno=%d", errno);
    325 
    326 	/* We expect the FIFO to be readble but not writable. */
    327 	RL(ret = poll(pfd, 2, 0));
    328 	ATF_REQUIRE_EQ_MSG(ret, 1, "got: %d", ret);
    329 	ATF_REQUIRE_EQ_MSG(pfd[0].revents, POLLIN|POLLRDNORM,
    330 	    "pfd[0].revents=0x%x", pfd[0].revents);
    331 	ATF_REQUIRE_EQ_MSG(pfd[1].revents, 0,
    332 	    "pfd[1].revents=0x%x", pfd[1].revents);
    333 
    334 	/* Read a single byte of data from the FIFO. */
    335 	RL(nread = read(rfd, buf, 1));
    336 	ATF_REQUIRE_EQ_MSG(nread, 1, "nread=%zd", nread);
    337 
    338 	/*
    339 	 * Because we have read only a single byte out, there will
    340 	 * be insufficient space for a pipe_buf-sized message, so
    341 	 * the FIFO should still not be writable.
    342 	 */
    343 	RL(ret = poll(pfd, 2, 0));
    344 	ATF_REQUIRE_EQ_MSG(ret, 1, "got: %d", ret);
    345 	ATF_REQUIRE_EQ_MSG(pfd[0].revents, POLLIN|POLLRDNORM,
    346 	    "pfd[0].revents=0x%x", pfd[0].revents);
    347 	ATF_REQUIRE_EQ_MSG(pfd[1].revents, 0,
    348 	    "pfd[1].revents=0x%x", pfd[1].revents);
    349 
    350 	/*
    351 	 * Now read enough so that exactly pipe_buf space should
    352 	 * be available.  The FIFO should be writable after that.
    353 	 * N.B. we don't care if it's readable at this point.
    354 	 */
    355 	RL(nread = read(rfd, buf, pipe_buf - 1));
    356 	ATF_REQUIRE_EQ_MSG(nread, pipe_buf - 1, "nread=%zd pipe_buf-1=%ld",
    357 	    nread, pipe_buf - 1);
    358 	RL(ret = poll(pfd, 2, 0));
    359 	ATF_REQUIRE_MSG(ret >= 1, "got: %d", ret);
    360 	ATF_REQUIRE_EQ_MSG(pfd[1].revents, POLLOUT|POLLWRNORM,
    361 	    "pfd[1].revents=0x%x", pfd[1].revents);
    362 
    363 	/*
    364 	 * Now read all of the data out of the FIFO and ensure that
    365 	 * we get back to the initial state.
    366 	 */
    367 	while (read(rfd, buf, pipe_buf) != -1) {
    368 		continue;
    369 	}
    370 	ATF_REQUIRE_EQ_MSG(errno, EAGAIN, "errno=%d", errno);
    371 
    372 	RL(ret = poll(pfd, 2, 0));
    373 	ATF_REQUIRE_EQ_MSG(ret, 1, "got: %d", ret);
    374 	ATF_REQUIRE_EQ_MSG(pfd[0].revents, 0,
    375 	    "pfd[0].revents=0x%x", pfd[0].revents);
    376 	ATF_REQUIRE_EQ_MSG(pfd[1].revents, POLLOUT|POLLWRNORM,
    377 	    "pfd[1].revents=0x%x", pfd[1].revents);
    378 
    379 	RL(close(wfd));
    380 	RL(close(rfd));
    381 }
    382 
    383 ATF_TC_CLEANUP(fifo_inout, tc)
    384 {
    385 	(void)unlink(fifo_path);
    386 }
    387 
    388 ATF_TC_WITH_CLEANUP(fifo_hup1);
    389 ATF_TC_HEAD(fifo_hup1, tc)
    390 {
    391 	atf_tc_set_md_var(tc, "descr",
    392 	    "Check POLLHUP behavior with fifos [1]");
    393 }
    394 
    395 ATF_TC_BODY(fifo_hup1, tc)
    396 {
    397 	struct pollfd pfd;
    398 	int rfd, wfd;
    399 	int ret;
    400 
    401 	fifo_support();
    402 
    403 	RL(mkfifo(fifo_path, 0600));
    404 	RL(rfd = open(fifo_path, O_RDONLY | O_NONBLOCK));
    405 	RL(wfd = open(fifo_path, O_WRONLY));
    406 
    407 	memset(&pfd, 0, sizeof(pfd));
    408 	pfd.fd = rfd;
    409 	pfd.events = POLLIN;
    410 
    411 	RL(close(wfd));
    412 
    413 	RL(ret = poll(&pfd, 1, 0));
    414 	ATF_REQUIRE_EQ_MSG(ret, 1, "got: %d", ret);
    415 	ATF_REQUIRE_EQ_MSG((pfd.revents & (POLLHUP|POLLOUT)), POLLHUP,
    416 	    "revents=0x%x expected POLLHUP=0x%x and not POLLOUT=0x%x",
    417 	    pfd.revents, POLLHUP, POLLOUT);
    418 
    419 	/*
    420 	 * Check that POLLHUP is cleared when a writer re-connects.
    421 	 * Since the writer will not put any data into the FIFO, we
    422 	 * expect no events.
    423 	 */
    424 	memset(&pfd, 0, sizeof(pfd));
    425 	pfd.fd = rfd;
    426 	pfd.events = POLLIN;
    427 
    428 	RL(wfd = open(fifo_path, O_WRONLY));
    429 	RL(ret = poll(&pfd, 1, 0));
    430 	ATF_REQUIRE_EQ_MSG(ret, 0, "got: %d", ret);
    431 }
    432 
    433 ATF_TC_CLEANUP(fifo_hup1, tc)
    434 {
    435 	(void)unlink(fifo_path);
    436 }
    437 
    438 ATF_TC_WITH_CLEANUP(fifo_hup2);
    439 ATF_TC_HEAD(fifo_hup2, tc)
    440 {
    441 	atf_tc_set_md_var(tc, "descr",
    442 	    "Check POLLHUP behavior with fifos [2]");
    443 }
    444 
    445 ATF_TC_BODY(fifo_hup2, tc)
    446 {
    447 	struct pollfd pfd;
    448 	int rfd, wfd;
    449 	pid_t pid;
    450 	struct timespec ts1, ts2;
    451 	int ret;
    452 
    453 	fifo_support();
    454 
    455 	RL(mkfifo(fifo_path, 0600));
    456 	RL(rfd = open(fifo_path, O_RDONLY | O_NONBLOCK));
    457 	RL(wfd = open(fifo_path, O_WRONLY));
    458 
    459 	memset(&pfd, 0, sizeof(pfd));
    460 	pfd.fd = rfd;
    461 	pfd.events = POLLIN;
    462 
    463 	RL(pid = fork());
    464 	if (pid == 0) {
    465 		if (close(rfd))
    466 			_exit(1);
    467 		sleep(5);
    468 		if (close(wfd))
    469 			_exit(1);
    470 		_exit(0);
    471 	}
    472 	RL(close(wfd));
    473 
    474 	RL(clock_gettime(CLOCK_MONOTONIC, &ts1));
    475 	RL(ret = poll(&pfd, 1, INFTIM));
    476 	ATF_REQUIRE_EQ_MSG(ret, 1, "got: %d", ret);
    477 	RL(clock_gettime(CLOCK_MONOTONIC, &ts2));
    478 
    479 	/* Make sure at least a couple of seconds have elapsed. */
    480 	ATF_REQUIRE_MSG(ts2.tv_sec - ts1.tv_sec >= 2,
    481 	    "ts1=%lld.%09ld ts2=%lld.%09ld",
    482 	    (long long)ts1.tv_sec, ts1.tv_nsec,
    483 	    (long long)ts2.tv_sec, ts2.tv_nsec);
    484 
    485 	ATF_REQUIRE_EQ_MSG((pfd.revents & (POLLHUP|POLLOUT)), POLLHUP,
    486 	    "revents=0x%x expected POLLHUP=0x%x and not POLLOUT=0x%x",
    487 	    pfd.revents, POLLHUP, POLLOUT);
    488 }
    489 
    490 ATF_TC_CLEANUP(fifo_hup2, tc)
    491 {
    492 	(void)unlink(fifo_path);
    493 }
    494 
    495 ATF_TP_ADD_TCS(tp)
    496 {
    497 
    498 	ATF_TP_ADD_TC(tp, 3way);
    499 	ATF_TP_ADD_TC(tp, basic);
    500 	ATF_TP_ADD_TC(tp, err);
    501 
    502 	ATF_TP_ADD_TC(tp, fifo_inout);
    503 	ATF_TP_ADD_TC(tp, fifo_hup1);
    504 	ATF_TP_ADD_TC(tp, fifo_hup2);
    505 
    506 	return atf_no_error();
    507 }
    508