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 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(3way); 89 ATF_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 100 ATF_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 151 ATF_TC(basic); 152 ATF_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 159 ATF_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 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 ATF_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