1/* $OpenBSD: t_poll.c,v 1.3 2022/05/28 18:39:39 mbuhl Exp $ */ 2/* $NetBSD: t_poll.c,v 1.4 2020/07/17 15:34:16 kamil 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 47static int desc; 48 49static void 50child1(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 61static void 62child2(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 74static void 75child3(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 88ATF_TC(3way); 89ATF_TC_HEAD(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 100ATF_TC_BODY(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 151ATF_TC(basic); 152ATF_TC_HEAD(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 159ATF_TC_BODY(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 ret = poll(&pfds[0], 1, 1); 179 ATF_REQUIRE_EQ_MSG(ret, 0, "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 ret = poll(&pfds[1], 1, 1); 187 ATF_REQUIRE_EQ_MSG(ret, 1, "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 ret = poll(pfds, 2, 1); 196 ATF_REQUIRE_EQ_MSG(ret, 1, "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 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 ATF_REQUIRE_EQ(close(fds[0]), 0); 215 ATF_REQUIRE_EQ(close(fds[1]), 0); 216} 217 218ATF_TC(err); 219ATF_TC_HEAD(err, tc) 220{ 221 atf_tc_set_md_var(tc, "descr", "Check errors from poll(2)"); 222} 223 224ATF_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 239ATF_TP_ADD_TCS(tp) 240{ 241 242 ATF_TP_ADD_TC(tp, 3way); 243 ATF_TP_ADD_TC(tp, basic); 244 ATF_TP_ADD_TC(tp, err); 245 246 return atf_no_error(); 247} 248