1 /* $OpenBSD: t_poll.c,v 1.1.1.1 2019/11/19 19:57:04 bluhm Exp $ */ 2 /* $NetBSD: t_poll.c,v 1.3 2012/03/18 07:00:52 jruoho Exp $ */ 3 4 /*- 5 * Copyright (c) 2011 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Matthias Scheler. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include "macros.h" 34 35 #include <sys/time.h> 36 #include <sys/wait.h> 37 38 #include "atf-c.h" 39 #include <errno.h> 40 #include <fcntl.h> 41 #include <paths.h> 42 #include <poll.h> 43 #include <stdio.h> 44 #include <signal.h> 45 #include <unistd.h> 46 47 static int desc; 48 49 static void 50 child1(void) 51 { 52 struct pollfd pfd; 53 54 pfd.fd = desc; 55 pfd.events = POLLIN | POLLHUP | POLLOUT; 56 57 (void)poll(&pfd, 1, 2000); 58 (void)printf("child1 exit\n"); 59 } 60 61 static void 62 child2(void) 63 { 64 struct pollfd pfd; 65 66 pfd.fd = desc; 67 pfd.events = POLLIN | POLLHUP | POLLOUT; 68 69 (void)sleep(1); 70 (void)poll(&pfd, 1, INFTIM); 71 (void)printf("child2 exit\n"); 72 } 73 74 static void 75 child3(void) 76 { 77 struct pollfd pfd; 78 79 (void)sleep(5); 80 81 pfd.fd = desc; 82 pfd.events = POLLIN | POLLHUP | POLLOUT; 83 84 (void)poll(&pfd, 1, INFTIM); 85 (void)printf("child3 exit\n"); 86 } 87 88 ATF_TC(poll_3way); 89 ATF_TC_HEAD(poll_3way, tc) 90 { 91 atf_tc_set_md_var(tc, "timeout", "15"); 92 atf_tc_set_md_var(tc, "descr", 93 "Check for 3-way collision for descriptor. First child comes " 94 "and polls on descriptor, second child comes and polls, first " 95 "child times out and exits, third child comes and polls. When " 96 "the wakeup event happens, the two remaining children should " 97 "both be awaken. (kern/17517)"); 98 } 99 100 ATF_TC_BODY(poll_3way, tc) 101 { 102 int pf[2]; 103 int status, i; 104 pid_t pid; 105 106 pipe(pf); 107 desc = pf[0]; 108 109 pid = fork(); 110 ATF_REQUIRE(pid >= 0); 111 112 if (pid == 0) { 113 (void)close(pf[1]); 114 child1(); 115 _exit(0); 116 /* NOTREACHED */ 117 } 118 119 pid = fork(); 120 ATF_REQUIRE(pid >= 0); 121 122 if (pid == 0) { 123 (void)close(pf[1]); 124 child2(); 125 _exit(0); 126 /* NOTREACHED */ 127 } 128 129 pid = fork(); 130 ATF_REQUIRE( pid >= 0); 131 132 if (pid == 0) { 133 (void)close(pf[1]); 134 child3(); 135 _exit(0); 136 /* NOTREACHED */ 137 } 138 139 (void)sleep(10); 140 141 (void)printf("parent write\n"); 142 143 ATF_REQUIRE(write(pf[1], "konec\n", 6) == 6); 144 145 for(i = 0; i < 3; ++i) 146 (void)wait(&status); 147 148 (void)printf("parent terminated\n"); 149 } 150 151 ATF_TC(poll_basic); 152 ATF_TC_HEAD(poll_basic, tc) 153 { 154 atf_tc_set_md_var(tc, "timeout", "10"); 155 atf_tc_set_md_var(tc, "descr", 156 "Basis functionality test for poll(2)"); 157 } 158 159 ATF_TC_BODY(poll_basic, tc) 160 { 161 int fds[2]; 162 struct pollfd pfds[2]; 163 int ret; 164 165 ATF_REQUIRE_EQ(pipe(fds), 0); 166 167 pfds[0].fd = fds[0]; 168 pfds[0].events = POLLIN; 169 pfds[1].fd = fds[1]; 170 pfds[1].events = POLLOUT; 171 172 /* 173 * Check that we get a timeout waiting for data on the read end 174 * of our pipe. 175 */ 176 pfds[0].revents = -1; 177 pfds[1].revents = -1; 178 ATF_REQUIRE_EQ_MSG(ret = poll(&pfds[0], 1, 1), 0, 179 "got: %d", ret); 180 ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents); 181 ATF_REQUIRE_EQ_MSG(pfds[1].revents, -1, "got: %d", pfds[1].revents); 182 183 /* Check that the write end of the pipe as reported as ready. */ 184 pfds[0].revents = -1; 185 pfds[1].revents = -1; 186 ATF_REQUIRE_EQ_MSG(ret = poll(&pfds[1], 1, 1), 1, 187 "got: %d", ret); 188 ATF_REQUIRE_EQ_MSG(pfds[0].revents, -1, "got: %d", pfds[0].revents); 189 ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",\ 190 pfds[1].revents); 191 192 /* Check that only the write end of the pipe as reported as ready. */ 193 pfds[0].revents = -1; 194 pfds[1].revents = -1; 195 ATF_REQUIRE_EQ_MSG(ret = poll(pfds, 2, 1), 1, 196 "got: %d", ret); 197 ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents); 198 ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d", 199 pfds[1].revents); 200 201 /* Write data to our pipe. */ 202 ATF_REQUIRE_EQ(write(fds[1], "", 1), 1); 203 204 /* Check that both ends of our pipe are reported as ready. */ 205 pfds[0].revents = -1; 206 pfds[1].revents = -1; 207 ATF_REQUIRE_EQ_MSG(ret = poll(pfds, 2, 1), 2, 208 "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 ATF_REQUIRE_EQ(close(fds[0]), 0); 215 ATF_REQUIRE_EQ(close(fds[1]), 0); 216 } 217 218 ATF_TC(poll_err); 219 ATF_TC_HEAD(poll_err, tc) 220 { 221 atf_tc_set_md_var(tc, "descr", "Check errors from poll(2)"); 222 } 223 224 ATF_TC_BODY(poll_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 ATF_TC(pollts_basic); 240 ATF_TC_HEAD(pollts_basic, tc) 241 { 242 atf_tc_set_md_var(tc, "timeout", "10"); 243 atf_tc_set_md_var(tc, "descr", 244 "Basis functionality test for pollts(2)"); 245 } 246 247 ATF_TC_BODY(pollts_basic, tc) 248 { 249 int fds[2]; 250 struct pollfd pfds[2]; 251 struct timespec timeout; 252 int ret; 253 254 ATF_REQUIRE_EQ(pipe(fds), 0); 255 256 pfds[0].fd = fds[0]; 257 pfds[0].events = POLLIN; 258 pfds[1].fd = fds[1]; 259 pfds[1].events = POLLOUT; 260 261 /* Use a timeout of 1 second. */ 262 timeout.tv_sec = 1; 263 timeout.tv_nsec = 0; 264 265 /* 266 * Check that we get a timeout waiting for data on the read end 267 * of our pipe. 268 */ 269 pfds[0].revents = -1; 270 pfds[1].revents = -1; 271 ATF_REQUIRE_EQ_MSG(ret = pollts(&pfds[0], 1, &timeout, NULL), 0, 272 "got: %d", ret); 273 ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents); 274 ATF_REQUIRE_EQ_MSG(pfds[1].revents, -1, "got: %d", pfds[1].revents); 275 276 /* Check that the write end of the pipe as reported as ready. */ 277 pfds[0].revents = -1; 278 pfds[1].revents = -1; 279 ATF_REQUIRE_EQ_MSG(ret = pollts(&pfds[1], 1, &timeout, NULL), 1, 280 "got: %d", ret); 281 ATF_REQUIRE_EQ_MSG(pfds[0].revents, -1, "got: %d", pfds[0].revents); 282 ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",\ 283 pfds[1].revents); 284 285 /* Check that only the write end of the pipe as reported as ready. */ 286 pfds[0].revents = -1; 287 pfds[1].revents = -1; 288 ATF_REQUIRE_EQ_MSG(ret = pollts(pfds, 2, &timeout, NULL), 1, 289 "got: %d", ret); 290 ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents); 291 ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d", 292 pfds[1].revents); 293 294 /* Write data to our pipe. */ 295 ATF_REQUIRE_EQ(write(fds[1], "", 1), 1); 296 297 /* Check that both ends of our pipe are reported as ready. */ 298 pfds[0].revents = -1; 299 pfds[1].revents = -1; 300 ATF_REQUIRE_EQ_MSG(ret = pollts(pfds, 2, &timeout, NULL), 2, 301 "got: %d", ret); 302 ATF_REQUIRE_EQ_MSG(pfds[0].revents, POLLIN, "got: %d", 303 pfds[0].revents); 304 ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d", 305 pfds[1].revents); 306 307 ATF_REQUIRE_EQ(close(fds[0]), 0); 308 ATF_REQUIRE_EQ(close(fds[1]), 0); 309 } 310 311 ATF_TC(pollts_err); 312 ATF_TC_HEAD(pollts_err, tc) 313 { 314 atf_tc_set_md_var(tc, "descr", "Check errors from pollts(2)"); 315 } 316 317 ATF_TC_BODY(pollts_err, tc) 318 { 319 struct timespec timeout; 320 struct pollfd pfd; 321 int fd = 0; 322 323 pfd.fd = fd; 324 pfd.events = POLLIN; 325 326 timeout.tv_sec = 1; 327 timeout.tv_nsec = 0; 328 329 errno = 0; 330 ATF_REQUIRE_ERRNO(EFAULT, pollts((void *)-1, 1, &timeout, NULL) == -1); 331 332 timeout.tv_sec = -1; 333 timeout.tv_nsec = -1; 334 335 errno = 0; 336 ATF_REQUIRE_ERRNO(EINVAL, pollts(&pfd, 1, &timeout, NULL) == -1); 337 } 338 339 ATF_TC(pollts_sigmask); 340 ATF_TC_HEAD(pollts_sigmask, tc) 341 { 342 atf_tc_set_md_var(tc, "timeout", "10"); 343 atf_tc_set_md_var(tc, "descr", 344 "Check that pollts(2) restores the signal mask (PR kern/44986)"); 345 } 346 347 ATF_TC_BODY(pollts_sigmask, tc) 348 { 349 int fd; 350 struct pollfd pfd; 351 struct timespec timeout; 352 sigset_t mask; 353 int ret; 354 355 fd = open(_PATH_DEVNULL, O_RDONLY); 356 ATF_REQUIRE(fd >= 0); 357 358 pfd.fd = fd; 359 pfd.events = POLLIN; 360 361 /* Use a timeout of 1 second. */ 362 timeout.tv_sec = 1; 363 timeout.tv_nsec = 0; 364 365 /* Unblock all signals. */ 366 ATF_REQUIRE_EQ(sigfillset(&mask), 0); 367 ATF_REQUIRE_EQ(sigprocmask(SIG_UNBLOCK, &mask, NULL), 0); 368 369 /* 370 * Check that pollts(2) immediately returns. We block *all* 371 * signals during pollts(2). 372 */ 373 ATF_REQUIRE_EQ_MSG(ret = pollts(&pfd, 1, &timeout, &mask), 1, 374 "got: %d", ret); 375 376 /* Check that signals are now longer blocked. */ 377 ATF_REQUIRE_EQ(sigprocmask(SIG_SETMASK, NULL, &mask), 0); 378 ATF_REQUIRE_EQ_MSG(sigismember(&mask, SIGUSR1), 0, 379 "signal mask was changed."); 380 381 ATF_REQUIRE_EQ(close(fd), 0); 382 } 383 384 ATF_TP_ADD_TCS(tp) 385 { 386 387 ATF_TP_ADD_TC(tp, poll_3way); 388 ATF_TP_ADD_TC(tp, poll_basic); 389 ATF_TP_ADD_TC(tp, poll_err); 390 /* 391 * Adjusted for OpenBSD, not supported 392 * ATF_TP_ADD_TC(tp, pollts_basic); 393 * ATF_TP_ADD_TC(tp, pollts_err); 394 * ATF_TP_ADD_TC(tp, pollts_sigmask); 395 */ 396 397 return atf_no_error(); 398 } 399