1 /* $NetBSD: t_poll.c,v 1.8 2021/10/02 17:32:55 thorpej 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 105 pipe(pf); 106 desc = pf[0]; 107 108 pid = fork(); 109 ATF_REQUIRE(pid >= 0); 110 111 if (pid == 0) { 112 (void)close(pf[1]); 113 child1(); 114 _exit(0); 115 /* NOTREACHED */ 116 } 117 118 pid = fork(); 119 ATF_REQUIRE(pid >= 0); 120 121 if (pid == 0) { 122 (void)close(pf[1]); 123 child2(); 124 _exit(0); 125 /* NOTREACHED */ 126 } 127 128 pid = fork(); 129 ATF_REQUIRE( pid >= 0); 130 131 if (pid == 0) { 132 (void)close(pf[1]); 133 child3(); 134 _exit(0); 135 /* NOTREACHED */ 136 } 137 138 (void)sleep(10); 139 140 (void)printf("parent write\n"); 141 142 ATF_REQUIRE(write(pf[1], "konec\n", 6) == 6); 143 144 for(i = 0; i < 3; ++i) 145 (void)wait(&status); 146 147 (void)printf("parent terminated\n"); 148 } 149 150 ATF_TC(basic); 151 ATF_TC_HEAD(basic, tc) 152 { 153 atf_tc_set_md_var(tc, "timeout", "10"); 154 atf_tc_set_md_var(tc, "descr", 155 "Basis functionality test for poll(2)"); 156 } 157 158 ATF_TC_BODY(basic, tc) 159 { 160 int fds[2]; 161 struct pollfd pfds[2]; 162 int ret; 163 164 ATF_REQUIRE_EQ(pipe(fds), 0); 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 ATF_REQUIRE_EQ_MSG(ret = poll(&pfds[0], 1, 1), 0, 178 "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 ATF_REQUIRE_EQ_MSG(ret = poll(&pfds[1], 1, 1), 1, 186 "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 ATF_REQUIRE_EQ_MSG(ret = poll(pfds, 2, 1), 1, 195 "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 ATF_REQUIRE_EQ(write(fds[1], "", 1), 1); 202 203 /* Check that both ends of our pipe are reported as ready. */ 204 pfds[0].revents = -1; 205 pfds[1].revents = -1; 206 ATF_REQUIRE_EQ_MSG(ret = poll(pfds, 2, 1), 2, 207 "got: %d", ret); 208 ATF_REQUIRE_EQ_MSG(pfds[0].revents, POLLIN, "got: %d", 209 pfds[0].revents); 210 ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d", 211 pfds[1].revents); 212 213 ATF_REQUIRE_EQ(close(fds[0]), 0); 214 ATF_REQUIRE_EQ(close(fds[1]), 0); 215 } 216 217 ATF_TC(err); 218 ATF_TC_HEAD(err, tc) 219 { 220 atf_tc_set_md_var(tc, "descr", "Check errors from poll(2)"); 221 } 222 223 ATF_TC_BODY(err, tc) 224 { 225 struct pollfd pfd; 226 int fd = 0; 227 228 pfd.fd = fd; 229 pfd.events = POLLIN; 230 231 errno = 0; 232 ATF_REQUIRE_ERRNO(EFAULT, poll((struct pollfd *)-1, 1, -1) == -1); 233 234 errno = 0; 235 ATF_REQUIRE_ERRNO(EINVAL, poll(&pfd, 1, -2) == -1); 236 } 237 238 static const char fifo_path[] = "pollhup_fifo"; 239 240 static void 241 fifo_support(void) 242 { 243 errno = 0; 244 if (mkfifo(fifo_path, 0600) == 0) { 245 ATF_REQUIRE(unlink(fifo_path) == 0); 246 return; 247 } 248 249 if (errno == EOPNOTSUPP) { 250 atf_tc_skip("the kernel does not support FIFOs"); 251 } else { 252 atf_tc_fail("mkfifo(2) failed"); 253 } 254 } 255 256 ATF_TC_WITH_CLEANUP(fifo_inout); 257 ATF_TC_HEAD(fifo_inout, tc) 258 { 259 atf_tc_set_md_var(tc, "descr", 260 "Check POLLIN/POLLOUT behavior with fifos"); 261 } 262 263 ATF_TC_BODY(fifo_inout, tc) 264 { 265 struct pollfd pfd[2]; 266 char *buf; 267 int rfd, wfd; 268 long pipe_buf; 269 270 fifo_support(); 271 272 ATF_REQUIRE(mkfifo(fifo_path, 0600) == 0); 273 ATF_REQUIRE((rfd = open(fifo_path, O_RDONLY | O_NONBLOCK)) >= 0); 274 ATF_REQUIRE((wfd = open(fifo_path, O_WRONLY | O_NONBLOCK)) >= 0); 275 276 /* Get the maximum atomic pipe write size. */ 277 pipe_buf = fpathconf(wfd, _PC_PIPE_BUF); 278 ATF_REQUIRE(pipe_buf > 1); 279 280 buf = malloc(pipe_buf); 281 ATF_REQUIRE(buf != NULL); 282 283 memset(&pfd, 0, sizeof(pfd)); 284 pfd[0].fd = rfd; 285 pfd[0].events = POLLIN | POLLRDNORM; 286 pfd[1].fd = wfd; 287 pfd[1].events = POLLOUT | POLLWRNORM; 288 289 /* We expect the FIFO to be writable but not readable. */ 290 ATF_REQUIRE(poll(pfd, 2, 0) == 1); 291 ATF_REQUIRE(pfd[0].revents == 0); 292 ATF_REQUIRE(pfd[1].revents == (POLLOUT | POLLWRNORM)); 293 294 /* Write a single byte of data into the FIFO. */ 295 ATF_REQUIRE(write(wfd, buf, 1) == 1); 296 297 /* We expect the FIFO to be readable and writable. */ 298 ATF_REQUIRE(poll(pfd, 2, 0) == 2); 299 ATF_REQUIRE(pfd[0].revents == (POLLIN | POLLRDNORM)); 300 ATF_REQUIRE(pfd[1].revents == (POLLOUT | POLLWRNORM)); 301 302 /* Read that single byte back out. */ 303 ATF_REQUIRE(read(rfd, buf, 1) == 1); 304 305 /* 306 * Write data into the FIFO until it is full, which is 307 * defined as insufficient buffer space to hold a the 308 * maximum atomic pipe write size. 309 */ 310 while (write(wfd, buf, pipe_buf) != -1) { 311 continue; 312 } 313 ATF_REQUIRE(errno == EAGAIN); 314 315 /* We expect the FIFO to be readble but not writable. */ 316 ATF_REQUIRE(poll(pfd, 2, 0) == 1); 317 ATF_REQUIRE(pfd[0].revents == (POLLIN | POLLRDNORM)); 318 ATF_REQUIRE(pfd[1].revents == 0); 319 320 /* Read a single byte of data from the FIFO. */ 321 ATF_REQUIRE(read(rfd, buf, 1) == 1); 322 323 /* 324 * Because we have read only a single byte out, there will 325 * be insufficient space for a pipe_buf-sized message, so 326 * the FIFO should still not be writable. 327 */ 328 ATF_REQUIRE(poll(pfd, 2, 0) == 1); 329 ATF_REQUIRE(pfd[0].revents == (POLLIN | POLLRDNORM)); 330 ATF_REQUIRE(pfd[1].revents == 0); 331 332 /* 333 * Now read enough so that exactly pipe_buf space should 334 * be available. The FIFO should be writable after that. 335 * N.B. we don't care if it's readable at this point. 336 */ 337 ATF_REQUIRE(read(rfd, buf, pipe_buf - 1) == pipe_buf - 1); 338 ATF_REQUIRE(poll(pfd, 2, 0) >= 1); 339 ATF_REQUIRE(pfd[1].revents == (POLLOUT | POLLWRNORM)); 340 341 /* 342 * Now read all of the data out of the FIFO and ensure that 343 * we get back to the initial state. 344 */ 345 while (read(rfd, buf, pipe_buf) != -1) { 346 continue; 347 } 348 ATF_REQUIRE(errno == EAGAIN); 349 350 ATF_REQUIRE(poll(pfd, 2, 0) == 1); 351 ATF_REQUIRE(pfd[0].revents == 0); 352 ATF_REQUIRE(pfd[1].revents == (POLLOUT | POLLWRNORM)); 353 354 (void)close(wfd); 355 (void)close(rfd); 356 } 357 358 ATF_TC_CLEANUP(fifo_inout, tc) 359 { 360 (void)unlink(fifo_path); 361 } 362 363 ATF_TC_WITH_CLEANUP(fifo_hup1); 364 ATF_TC_HEAD(fifo_hup1, tc) 365 { 366 atf_tc_set_md_var(tc, "descr", 367 "Check POLLHUP behavior with fifos [1]"); 368 } 369 370 ATF_TC_BODY(fifo_hup1, tc) 371 { 372 struct pollfd pfd; 373 int rfd, wfd; 374 375 fifo_support(); 376 377 ATF_REQUIRE(mkfifo(fifo_path, 0600) == 0); 378 ATF_REQUIRE((rfd = open(fifo_path, O_RDONLY | O_NONBLOCK)) >= 0); 379 ATF_REQUIRE((wfd = open(fifo_path, O_WRONLY)) >= 0); 380 381 memset(&pfd, 0, sizeof(pfd)); 382 pfd.fd = rfd; 383 pfd.events = POLLIN; 384 385 (void)close(wfd); 386 387 ATF_REQUIRE(poll(&pfd, 1, 0) == 1); 388 ATF_REQUIRE((pfd.revents & POLLHUP) != 0); 389 390 /* 391 * Check that POLLHUP is cleared when a writer re-connects. 392 * Since the writer will not put any data into the FIFO, we 393 * expect no events. 394 */ 395 memset(&pfd, 0, sizeof(pfd)); 396 pfd.fd = rfd; 397 pfd.events = POLLIN; 398 399 ATF_REQUIRE((wfd = open(fifo_path, O_WRONLY)) >= 0); 400 ATF_REQUIRE(poll(&pfd, 1, 0) == 0); 401 } 402 403 ATF_TC_CLEANUP(fifo_hup1, tc) 404 { 405 (void)unlink(fifo_path); 406 } 407 408 ATF_TC_WITH_CLEANUP(fifo_hup2); 409 ATF_TC_HEAD(fifo_hup2, tc) 410 { 411 atf_tc_set_md_var(tc, "descr", 412 "Check POLLHUP behavior with fifos [2]"); 413 } 414 415 ATF_TC_BODY(fifo_hup2, tc) 416 { 417 struct pollfd pfd; 418 int rfd, wfd; 419 pid_t pid; 420 struct timespec ts1, ts2; 421 422 fifo_support(); 423 424 ATF_REQUIRE(mkfifo(fifo_path, 0600) == 0); 425 ATF_REQUIRE((rfd = open(fifo_path, O_RDONLY | O_NONBLOCK)) >= 0); 426 ATF_REQUIRE((wfd = open(fifo_path, O_WRONLY)) >= 0); 427 428 memset(&pfd, 0, sizeof(pfd)); 429 pfd.fd = rfd; 430 pfd.events = POLLIN; 431 432 pid = fork(); 433 ATF_REQUIRE(pid >= 0); 434 435 if (pid == 0) { 436 (void)close(rfd); 437 sleep(5); 438 (void)close(wfd); 439 _exit(0); 440 } 441 (void)close(wfd); 442 443 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ts1) == 0); 444 ATF_REQUIRE(poll(&pfd, 1, INFTIM) == 1); 445 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ts2) == 0); 446 447 /* Make sure at least a couple of seconds have elapsed. */ 448 ATF_REQUIRE(ts2.tv_sec - ts1.tv_sec >= 2); 449 450 ATF_REQUIRE((pfd.revents & POLLHUP) != 0); 451 } 452 453 ATF_TC_CLEANUP(fifo_hup2, tc) 454 { 455 (void)unlink(fifo_path); 456 } 457 458 ATF_TP_ADD_TCS(tp) 459 { 460 461 ATF_TP_ADD_TC(tp, 3way); 462 ATF_TP_ADD_TC(tp, basic); 463 ATF_TP_ADD_TC(tp, err); 464 465 ATF_TP_ADD_TC(tp, fifo_inout); 466 ATF_TP_ADD_TC(tp, fifo_hup1); 467 ATF_TP_ADD_TC(tp, fifo_hup2); 468 469 return atf_no_error(); 470 } 471