1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2020 Jan Kokemüller 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 #include <sys/param.h> 30 #include <sys/event.h> 31 #include <sys/stat.h> 32 33 #include <errno.h> 34 #include <fcntl.h> 35 #include <limits.h> 36 #include <poll.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <time.h> 40 #include <unistd.h> 41 42 #include <atf-c.h> 43 44 ATF_TC_WITHOUT_HEAD(pipe_kqueue__write_end); 45 ATF_TC_BODY(pipe_kqueue__write_end, tc) 46 { 47 int p[2] = { -1, -1 }; 48 49 ATF_REQUIRE(pipe2(p, O_CLOEXEC | O_NONBLOCK) == 0); 50 ATF_REQUIRE(p[0] >= 0); 51 ATF_REQUIRE(p[1] >= 0); 52 53 int kq = kqueue(); 54 ATF_REQUIRE(kq >= 0); 55 56 struct kevent kev[32]; 57 EV_SET(&kev[0], p[1], EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, 0); 58 59 ATF_REQUIRE(kevent(kq, kev, 1, NULL, 0, NULL) == 0); 60 61 /* Test that EVFILT_WRITE behaves sensibly on the write end. */ 62 63 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev), 64 &(struct timespec) { 0, 0 }) == 1); 65 ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]); 66 ATF_REQUIRE(kev[0].filter == EVFILT_WRITE); 67 ATF_REQUIRE(kev[0].flags == EV_CLEAR); 68 ATF_REQUIRE(kev[0].fflags == 0); 69 ATF_REQUIRE(kev[0].data == 16384); 70 ATF_REQUIRE(kev[0].udata == 0); 71 72 /* Filling up the pipe should make the EVFILT_WRITE disappear. */ 73 74 char c = 0; 75 ssize_t r; 76 while ((r = write(p[1], &c, 1)) == 1) { 77 } 78 ATF_REQUIRE(r < 0); 79 ATF_REQUIRE(errno == EAGAIN || errno == EWOULDBLOCK); 80 81 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev), 82 &(struct timespec) { 0, 0 }) == 0); 83 84 /* Reading (PIPE_BUF - 1) bytes will not trigger a EVFILT_WRITE yet. */ 85 86 for (int i = 0; i < PIPE_BUF - 1; ++i) { 87 ATF_REQUIRE(read(p[0], &c, 1) == 1); 88 } 89 90 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev), 91 &(struct timespec) { 0, 0 }) == 0); 92 93 /* Reading one additional byte triggers the EVFILT_WRITE. */ 94 95 ATF_REQUIRE(read(p[0], &c, 1) == 1); 96 97 r = kevent(kq, NULL, 0, kev, nitems(kev), &(struct timespec) { 0, 0 }); 98 ATF_REQUIRE(r == 1); 99 ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]); 100 ATF_REQUIRE(kev[0].filter == EVFILT_WRITE); 101 ATF_REQUIRE(kev[0].flags == EV_CLEAR); 102 ATF_REQUIRE(kev[0].fflags == 0); 103 ATF_REQUIRE(kev[0].data == PIPE_BUF); 104 ATF_REQUIRE(kev[0].udata == 0); 105 106 /* 107 * Reading another byte triggers the EVFILT_WRITE again with a changed 108 * 'data' field. 109 */ 110 111 ATF_REQUIRE(read(p[0], &c, 1) == 1); 112 113 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev), 114 &(struct timespec) { 0, 0 }) == 1); 115 ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]); 116 ATF_REQUIRE(kev[0].filter == EVFILT_WRITE); 117 ATF_REQUIRE(kev[0].flags == EV_CLEAR); 118 ATF_REQUIRE(kev[0].fflags == 0); 119 ATF_REQUIRE(kev[0].data == PIPE_BUF + 1); 120 ATF_REQUIRE(kev[0].udata == 0); 121 122 /* 123 * Closing the read end should make a EV_EOF appear but leave the 'data' 124 * field unchanged. 125 */ 126 127 ATF_REQUIRE(close(p[0]) == 0); 128 129 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev), 130 &(struct timespec) { 0, 0 }) == 1); 131 ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]); 132 ATF_REQUIRE(kev[0].filter == EVFILT_WRITE); 133 ATF_REQUIRE(kev[0].flags == (EV_CLEAR | EV_EOF | EV_ONESHOT)); 134 ATF_REQUIRE(kev[0].fflags == 0); 135 ATF_REQUIRE(kev[0].data == PIPE_BUF + 1); 136 ATF_REQUIRE(kev[0].udata == 0); 137 138 ATF_REQUIRE(close(kq) == 0); 139 ATF_REQUIRE(close(p[1]) == 0); 140 } 141 142 ATF_TC_WITHOUT_HEAD(pipe_kqueue__closed_read_end); 143 ATF_TC_BODY(pipe_kqueue__closed_read_end, tc) 144 { 145 int p[2] = { -1, -1 }; 146 147 ATF_REQUIRE(pipe2(p, O_CLOEXEC | O_NONBLOCK) == 0); 148 ATF_REQUIRE(p[0] >= 0); 149 ATF_REQUIRE(p[1] >= 0); 150 151 ATF_REQUIRE(close(p[0]) == 0); 152 153 int kq = kqueue(); 154 ATF_REQUIRE(kq >= 0); 155 156 struct kevent kev[32]; 157 EV_SET(&kev[0], p[1], EVFILT_READ, EV_ADD | EV_CLEAR | EV_RECEIPT, /**/ 158 0, 0, 0); 159 EV_SET(&kev[1], p[1], EVFILT_WRITE, EV_ADD | EV_CLEAR | EV_RECEIPT, /**/ 160 0, 0, 0); 161 162 /* 163 * Trying to register EVFILT_WRITE when the pipe is closed leads to an 164 * EPIPE error. 165 */ 166 167 ATF_REQUIRE(kevent(kq, kev, 2, kev, 2, NULL) == 2); 168 ATF_REQUIRE((kev[0].flags & EV_ERROR) != 0); 169 ATF_REQUIRE(kev[0].data == 0); 170 ATF_REQUIRE((kev[1].flags & EV_ERROR) != 0); 171 ATF_REQUIRE(kev[1].data == EPIPE); 172 173 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev), 174 &(struct timespec) { 0, 0 }) == 1); 175 ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]); 176 ATF_REQUIRE(kev[0].filter == EVFILT_READ); 177 ATF_REQUIRE(kev[0].flags == (EV_EOF | EV_CLEAR | EV_RECEIPT)); 178 ATF_REQUIRE(kev[0].fflags == 0); 179 ATF_REQUIRE(kev[0].data == 0); 180 ATF_REQUIRE(kev[0].udata == 0); 181 182 ATF_REQUIRE(close(kq) == 0); 183 ATF_REQUIRE(close(p[1]) == 0); 184 } 185 186 ATF_TC_WITHOUT_HEAD(pipe_kqueue__closed_read_end_register_before_close); 187 ATF_TC_BODY(pipe_kqueue__closed_read_end_register_before_close, tc) 188 { 189 int p[2] = { -1, -1 }; 190 191 ATF_REQUIRE(pipe2(p, O_CLOEXEC | O_NONBLOCK) == 0); 192 ATF_REQUIRE(p[0] >= 0); 193 ATF_REQUIRE(p[1] >= 0); 194 195 int kq = kqueue(); 196 ATF_REQUIRE(kq >= 0); 197 198 struct kevent kev[32]; 199 EV_SET(&kev[0], p[1], EVFILT_READ, EV_ADD | EV_CLEAR | EV_RECEIPT, /**/ 200 0, 0, 0); 201 EV_SET(&kev[1], p[1], EVFILT_WRITE, EV_ADD | EV_CLEAR | EV_RECEIPT, /**/ 202 0, 0, 0); 203 204 /* 205 * Registering EVFILT_WRITE before the pipe is closed leads to a 206 * EVFILT_WRITE event with EV_EOF set. 207 */ 208 209 ATF_REQUIRE(kevent(kq, kev, 2, kev, 2, NULL) == 2); 210 ATF_REQUIRE((kev[0].flags & EV_ERROR) != 0); 211 ATF_REQUIRE(kev[0].data == 0); 212 ATF_REQUIRE((kev[1].flags & EV_ERROR) != 0); 213 ATF_REQUIRE(kev[1].data == 0); 214 215 ATF_REQUIRE(close(p[0]) == 0); 216 217 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev), 218 &(struct timespec) { 0, 0 }) == 2); 219 { 220 ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]); 221 ATF_REQUIRE(kev[0].filter == EVFILT_WRITE); 222 ATF_REQUIRE(kev[0].flags == 223 (EV_EOF | EV_CLEAR | EV_ONESHOT | EV_RECEIPT)); 224 ATF_REQUIRE(kev[0].fflags == 0); 225 ATF_REQUIRE(kev[0].data == 16384); 226 ATF_REQUIRE(kev[0].udata == 0); 227 } 228 { 229 ATF_REQUIRE(kev[1].ident == (uintptr_t)p[1]); 230 ATF_REQUIRE(kev[1].filter == EVFILT_READ); 231 ATF_REQUIRE(kev[1].flags == (EV_EOF | EV_CLEAR | EV_RECEIPT)); 232 ATF_REQUIRE(kev[1].fflags == 0); 233 ATF_REQUIRE(kev[1].data == 0); 234 ATF_REQUIRE(kev[1].udata == 0); 235 } 236 237 ATF_REQUIRE(close(kq) == 0); 238 ATF_REQUIRE(close(p[1]) == 0); 239 } 240 241 ATF_TC_WITHOUT_HEAD(pipe_kqueue__closed_write_end); 242 ATF_TC_BODY(pipe_kqueue__closed_write_end, tc) 243 { 244 struct kevent kev[32]; 245 ssize_t bytes, n; 246 int kq, p[2]; 247 char c; 248 249 ATF_REQUIRE(pipe2(p, O_CLOEXEC | O_NONBLOCK) == 0); 250 ATF_REQUIRE(p[0] >= 0); 251 ATF_REQUIRE(p[1] >= 0); 252 253 bytes = 0; 254 c = 0; 255 while ((n = write(p[1], &c, 1)) == 1) 256 bytes++; 257 ATF_REQUIRE(n < 0); 258 ATF_REQUIRE(errno == EAGAIN || errno == EWOULDBLOCK); 259 260 ATF_REQUIRE(close(p[1]) == 0); 261 262 kq = kqueue(); 263 ATF_REQUIRE(kq >= 0); 264 265 EV_SET(&kev[0], p[0], EVFILT_READ, EV_ADD | EV_CLEAR | EV_RECEIPT, 266 0, 0, 0); 267 EV_SET(&kev[1], p[0], EVFILT_WRITE, EV_ADD | EV_CLEAR | EV_RECEIPT, 268 0, 0, 0); 269 270 /* 271 * Trying to register EVFILT_WRITE when the pipe is closed leads to an 272 * EPIPE error. 273 */ 274 275 ATF_REQUIRE(kevent(kq, kev, 2, kev, 2, NULL) == 2); 276 ATF_REQUIRE((kev[0].flags & EV_ERROR) != 0); 277 ATF_REQUIRE(kev[0].data == 0); 278 ATF_REQUIRE((kev[1].flags & EV_ERROR) != 0); 279 ATF_REQUIRE(kev[1].data == EPIPE); 280 281 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev), 282 &(struct timespec) { 0, 0 }) == 1); 283 ATF_REQUIRE(kev[0].ident == (uintptr_t)p[0]); 284 ATF_REQUIRE(kev[0].filter == EVFILT_READ); 285 ATF_REQUIRE(kev[0].flags == (EV_EOF | EV_CLEAR | EV_RECEIPT)); 286 ATF_REQUIRE(kev[0].fflags == 0); 287 ATF_REQUIRE(kev[0].data == bytes); 288 ATF_REQUIRE(kev[0].udata == 0); 289 290 ATF_REQUIRE(close(kq) == 0); 291 ATF_REQUIRE(close(p[0]) == 0); 292 } 293 294 ATF_TC_WITHOUT_HEAD(pipe_kqueue__closed_write_end_register_before_close); 295 ATF_TC_BODY(pipe_kqueue__closed_write_end_register_before_close, tc) 296 { 297 struct kevent kev[32]; 298 ssize_t bytes, n; 299 int kq, p[2]; 300 char c; 301 302 ATF_REQUIRE(pipe2(p, O_CLOEXEC | O_NONBLOCK) == 0); 303 ATF_REQUIRE(p[0] >= 0); 304 ATF_REQUIRE(p[1] >= 0); 305 306 kq = kqueue(); 307 ATF_REQUIRE(kq >= 0); 308 309 EV_SET(&kev[0], p[0], EVFILT_READ, EV_ADD | EV_CLEAR | EV_RECEIPT, 310 0, 0, 0); 311 EV_SET(&kev[1], p[0], EVFILT_WRITE, EV_ADD | EV_CLEAR | EV_RECEIPT, 312 0, 0, 0); 313 314 /* 315 * Registering EVFILT_WRITE before the pipe is closed leads to a 316 * EVFILT_WRITE event with EV_EOF set. 317 */ 318 319 ATF_REQUIRE(kevent(kq, kev, 2, kev, 2, NULL) == 2); 320 ATF_REQUIRE((kev[0].flags & EV_ERROR) != 0); 321 ATF_REQUIRE(kev[0].data == 0); 322 ATF_REQUIRE((kev[1].flags & EV_ERROR) != 0); 323 ATF_REQUIRE(kev[1].data == 0); 324 325 bytes = 0; 326 c = 0; 327 while ((n = write(p[1], &c, 1)) == 1) 328 bytes++; 329 ATF_REQUIRE(n < 0); 330 ATF_REQUIRE(errno == EAGAIN || errno == EWOULDBLOCK); 331 332 ATF_REQUIRE(close(p[1]) == 0); 333 334 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev), 335 &(struct timespec){ 0, 0 }) == 2); 336 337 ATF_REQUIRE(kev[0].ident == (uintptr_t)p[0]); 338 ATF_REQUIRE(kev[0].filter == EVFILT_WRITE); 339 ATF_REQUIRE(kev[0].flags == 340 (EV_EOF | EV_CLEAR | EV_ONESHOT | EV_RECEIPT)); 341 ATF_REQUIRE(kev[0].fflags == 0); 342 ATF_REQUIRE(kev[0].data > 0); 343 ATF_REQUIRE(kev[0].udata == 0); 344 345 ATF_REQUIRE(kev[1].ident == (uintptr_t)p[0]); 346 ATF_REQUIRE(kev[1].filter == EVFILT_READ); 347 ATF_REQUIRE(kev[1].flags == (EV_EOF | EV_CLEAR | EV_RECEIPT)); 348 ATF_REQUIRE(kev[1].fflags == 0); 349 ATF_REQUIRE(kev[1].data == bytes); 350 ATF_REQUIRE(kev[1].udata == 0); 351 352 ATF_REQUIRE(close(kq) == 0); 353 ATF_REQUIRE(close(p[0]) == 0); 354 } 355 356 ATF_TP_ADD_TCS(tp) 357 { 358 ATF_TP_ADD_TC(tp, pipe_kqueue__write_end); 359 ATF_TP_ADD_TC(tp, pipe_kqueue__closed_read_end); 360 ATF_TP_ADD_TC(tp, pipe_kqueue__closed_read_end_register_before_close); 361 ATF_TP_ADD_TC(tp, pipe_kqueue__closed_write_end); 362 ATF_TP_ADD_TC(tp, pipe_kqueue__closed_write_end_register_before_close); 363 364 return atf_no_error(); 365 } 366