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 __FBSDID("$FreeBSD$"); 30 31 #include <sys/param.h> 32 #include <sys/event.h> 33 #include <sys/stat.h> 34 35 #include <errno.h> 36 #include <fcntl.h> 37 #include <limits.h> 38 #include <poll.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <time.h> 42 #include <unistd.h> 43 44 #include <atf-c.h> 45 46 ATF_TC_WITHOUT_HEAD(pipe_kqueue__write_end); 47 ATF_TC_BODY(pipe_kqueue__write_end, tc) 48 { 49 int p[2] = { -1, -1 }; 50 51 ATF_REQUIRE(pipe2(p, O_CLOEXEC | O_NONBLOCK) == 0); 52 ATF_REQUIRE(p[0] >= 0); 53 ATF_REQUIRE(p[1] >= 0); 54 55 int kq = kqueue(); 56 ATF_REQUIRE(kq >= 0); 57 58 struct kevent kev[32]; 59 EV_SET(&kev[0], p[1], EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, 0); 60 61 ATF_REQUIRE(kevent(kq, kev, 1, NULL, 0, NULL) == 0); 62 63 /* Test that EVFILT_WRITE behaves sensibly on the write end. */ 64 65 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev), 66 &(struct timespec) { 0, 0 }) == 1); 67 ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]); 68 ATF_REQUIRE(kev[0].filter == EVFILT_WRITE); 69 ATF_REQUIRE(kev[0].flags == EV_CLEAR); 70 ATF_REQUIRE(kev[0].fflags == 0); 71 ATF_REQUIRE(kev[0].data == 16384); 72 ATF_REQUIRE(kev[0].udata == 0); 73 74 /* Filling up the pipe should make the EVFILT_WRITE disappear. */ 75 76 char c = 0; 77 ssize_t r; 78 while ((r = write(p[1], &c, 1)) == 1) { 79 } 80 ATF_REQUIRE(r < 0); 81 ATF_REQUIRE(errno == EAGAIN || errno == EWOULDBLOCK); 82 83 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev), 84 &(struct timespec) { 0, 0 }) == 0); 85 86 /* Reading (PIPE_BUF - 1) bytes will not trigger a EVFILT_WRITE yet. */ 87 88 for (int i = 0; i < PIPE_BUF - 1; ++i) { 89 ATF_REQUIRE(read(p[0], &c, 1) == 1); 90 } 91 92 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev), 93 &(struct timespec) { 0, 0 }) == 0); 94 95 /* Reading one additional byte triggers the EVFILT_WRITE. */ 96 97 ATF_REQUIRE(read(p[0], &c, 1) == 1); 98 99 r = kevent(kq, NULL, 0, kev, nitems(kev), &(struct timespec) { 0, 0 }); 100 ATF_REQUIRE(r == 1); 101 ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]); 102 ATF_REQUIRE(kev[0].filter == EVFILT_WRITE); 103 ATF_REQUIRE(kev[0].flags == EV_CLEAR); 104 ATF_REQUIRE(kev[0].fflags == 0); 105 ATF_REQUIRE(kev[0].data == PIPE_BUF); 106 ATF_REQUIRE(kev[0].udata == 0); 107 108 /* 109 * Reading another byte triggers the EVFILT_WRITE again with a changed 110 * 'data' field. 111 */ 112 113 ATF_REQUIRE(read(p[0], &c, 1) == 1); 114 115 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev), 116 &(struct timespec) { 0, 0 }) == 1); 117 ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]); 118 ATF_REQUIRE(kev[0].filter == EVFILT_WRITE); 119 ATF_REQUIRE(kev[0].flags == EV_CLEAR); 120 ATF_REQUIRE(kev[0].fflags == 0); 121 ATF_REQUIRE(kev[0].data == PIPE_BUF + 1); 122 ATF_REQUIRE(kev[0].udata == 0); 123 124 /* 125 * Closing the read end should make a EV_EOF appear but leave the 'data' 126 * field unchanged. 127 */ 128 129 ATF_REQUIRE(close(p[0]) == 0); 130 131 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev), 132 &(struct timespec) { 0, 0 }) == 1); 133 ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]); 134 ATF_REQUIRE(kev[0].filter == EVFILT_WRITE); 135 ATF_REQUIRE(kev[0].flags == (EV_CLEAR | EV_EOF | EV_ONESHOT)); 136 ATF_REQUIRE(kev[0].fflags == 0); 137 ATF_REQUIRE(kev[0].data == PIPE_BUF + 1); 138 ATF_REQUIRE(kev[0].udata == 0); 139 140 ATF_REQUIRE(close(kq) == 0); 141 ATF_REQUIRE(close(p[1]) == 0); 142 } 143 144 ATF_TC_WITHOUT_HEAD(pipe_kqueue__closed_read_end); 145 ATF_TC_BODY(pipe_kqueue__closed_read_end, tc) 146 { 147 int p[2] = { -1, -1 }; 148 149 ATF_REQUIRE(pipe2(p, O_CLOEXEC | O_NONBLOCK) == 0); 150 ATF_REQUIRE(p[0] >= 0); 151 ATF_REQUIRE(p[1] >= 0); 152 153 ATF_REQUIRE(close(p[0]) == 0); 154 155 int kq = kqueue(); 156 ATF_REQUIRE(kq >= 0); 157 158 struct kevent kev[32]; 159 EV_SET(&kev[0], p[1], EVFILT_READ, EV_ADD | EV_CLEAR | EV_RECEIPT, /**/ 160 0, 0, 0); 161 EV_SET(&kev[1], p[1], EVFILT_WRITE, EV_ADD | EV_CLEAR | EV_RECEIPT, /**/ 162 0, 0, 0); 163 164 /* 165 * Trying to register EVFILT_WRITE when the pipe is closed leads to an 166 * EPIPE error. 167 */ 168 169 ATF_REQUIRE(kevent(kq, kev, 2, kev, 2, NULL) == 2); 170 ATF_REQUIRE((kev[0].flags & EV_ERROR) != 0); 171 ATF_REQUIRE(kev[0].data == 0); 172 ATF_REQUIRE((kev[1].flags & EV_ERROR) != 0); 173 ATF_REQUIRE(kev[1].data == EPIPE); 174 175 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev), 176 &(struct timespec) { 0, 0 }) == 1); 177 ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]); 178 ATF_REQUIRE(kev[0].filter == EVFILT_READ); 179 ATF_REQUIRE(kev[0].flags == (EV_EOF | EV_CLEAR | EV_RECEIPT)); 180 ATF_REQUIRE(kev[0].fflags == 0); 181 ATF_REQUIRE(kev[0].data == 0); 182 ATF_REQUIRE(kev[0].udata == 0); 183 184 ATF_REQUIRE(close(kq) == 0); 185 ATF_REQUIRE(close(p[1]) == 0); 186 } 187 188 ATF_TC_WITHOUT_HEAD(pipe_kqueue__closed_read_end_register_before_close); 189 ATF_TC_BODY(pipe_kqueue__closed_read_end_register_before_close, tc) 190 { 191 int p[2] = { -1, -1 }; 192 193 ATF_REQUIRE(pipe2(p, O_CLOEXEC | O_NONBLOCK) == 0); 194 ATF_REQUIRE(p[0] >= 0); 195 ATF_REQUIRE(p[1] >= 0); 196 197 int kq = kqueue(); 198 ATF_REQUIRE(kq >= 0); 199 200 struct kevent kev[32]; 201 EV_SET(&kev[0], p[1], EVFILT_READ, EV_ADD | EV_CLEAR | EV_RECEIPT, /**/ 202 0, 0, 0); 203 EV_SET(&kev[1], p[1], EVFILT_WRITE, EV_ADD | EV_CLEAR | EV_RECEIPT, /**/ 204 0, 0, 0); 205 206 /* 207 * Registering EVFILT_WRITE before the pipe is closed leads to a 208 * EVFILT_WRITE event with EV_EOF set. 209 */ 210 211 ATF_REQUIRE(kevent(kq, kev, 2, kev, 2, NULL) == 2); 212 ATF_REQUIRE((kev[0].flags & EV_ERROR) != 0); 213 ATF_REQUIRE(kev[0].data == 0); 214 ATF_REQUIRE((kev[1].flags & EV_ERROR) != 0); 215 ATF_REQUIRE(kev[1].data == 0); 216 217 ATF_REQUIRE(close(p[0]) == 0); 218 219 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev), 220 &(struct timespec) { 0, 0 }) == 2); 221 { 222 ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]); 223 ATF_REQUIRE(kev[0].filter == EVFILT_WRITE); 224 ATF_REQUIRE(kev[0].flags == 225 (EV_EOF | EV_CLEAR | EV_ONESHOT | EV_RECEIPT)); 226 ATF_REQUIRE(kev[0].fflags == 0); 227 ATF_REQUIRE(kev[0].data == 16384); 228 ATF_REQUIRE(kev[0].udata == 0); 229 } 230 { 231 ATF_REQUIRE(kev[1].ident == (uintptr_t)p[1]); 232 ATF_REQUIRE(kev[1].filter == EVFILT_READ); 233 ATF_REQUIRE(kev[1].flags == (EV_EOF | EV_CLEAR | EV_RECEIPT)); 234 ATF_REQUIRE(kev[1].fflags == 0); 235 ATF_REQUIRE(kev[1].data == 0); 236 ATF_REQUIRE(kev[1].udata == 0); 237 } 238 239 ATF_REQUIRE(close(kq) == 0); 240 ATF_REQUIRE(close(p[1]) == 0); 241 } 242 243 ATF_TC_WITHOUT_HEAD(pipe_kqueue__closed_write_end); 244 ATF_TC_BODY(pipe_kqueue__closed_write_end, tc) 245 { 246 struct kevent kev[32]; 247 ssize_t bytes, n; 248 int kq, p[2]; 249 char c; 250 251 ATF_REQUIRE(pipe2(p, O_CLOEXEC | O_NONBLOCK) == 0); 252 ATF_REQUIRE(p[0] >= 0); 253 ATF_REQUIRE(p[1] >= 0); 254 255 bytes = 0; 256 c = 0; 257 while ((n = write(p[1], &c, 1)) == 1) 258 bytes++; 259 ATF_REQUIRE(n < 0); 260 ATF_REQUIRE(errno == EAGAIN || errno == EWOULDBLOCK); 261 262 ATF_REQUIRE(close(p[1]) == 0); 263 264 kq = kqueue(); 265 ATF_REQUIRE(kq >= 0); 266 267 EV_SET(&kev[0], p[0], EVFILT_READ, EV_ADD | EV_CLEAR | EV_RECEIPT, 268 0, 0, 0); 269 EV_SET(&kev[1], p[0], EVFILT_WRITE, EV_ADD | EV_CLEAR | EV_RECEIPT, 270 0, 0, 0); 271 272 /* 273 * Trying to register EVFILT_WRITE when the pipe is closed leads to an 274 * EPIPE error. 275 */ 276 277 ATF_REQUIRE(kevent(kq, kev, 2, kev, 2, NULL) == 2); 278 ATF_REQUIRE((kev[0].flags & EV_ERROR) != 0); 279 ATF_REQUIRE(kev[0].data == 0); 280 ATF_REQUIRE((kev[1].flags & EV_ERROR) != 0); 281 ATF_REQUIRE(kev[1].data == EPIPE); 282 283 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev), 284 &(struct timespec) { 0, 0 }) == 1); 285 ATF_REQUIRE(kev[0].ident == (uintptr_t)p[0]); 286 ATF_REQUIRE(kev[0].filter == EVFILT_READ); 287 ATF_REQUIRE(kev[0].flags == (EV_EOF | EV_CLEAR | EV_RECEIPT)); 288 ATF_REQUIRE(kev[0].fflags == 0); 289 ATF_REQUIRE(kev[0].data == bytes); 290 ATF_REQUIRE(kev[0].udata == 0); 291 292 ATF_REQUIRE(close(kq) == 0); 293 ATF_REQUIRE(close(p[0]) == 0); 294 } 295 296 ATF_TC_WITHOUT_HEAD(pipe_kqueue__closed_write_end_register_before_close); 297 ATF_TC_BODY(pipe_kqueue__closed_write_end_register_before_close, tc) 298 { 299 struct kevent kev[32]; 300 ssize_t bytes, n; 301 int kq, p[2]; 302 char c; 303 304 ATF_REQUIRE(pipe2(p, O_CLOEXEC | O_NONBLOCK) == 0); 305 ATF_REQUIRE(p[0] >= 0); 306 ATF_REQUIRE(p[1] >= 0); 307 308 kq = kqueue(); 309 ATF_REQUIRE(kq >= 0); 310 311 EV_SET(&kev[0], p[0], EVFILT_READ, EV_ADD | EV_CLEAR | EV_RECEIPT, 312 0, 0, 0); 313 EV_SET(&kev[1], p[0], EVFILT_WRITE, EV_ADD | EV_CLEAR | EV_RECEIPT, 314 0, 0, 0); 315 316 /* 317 * Registering EVFILT_WRITE before the pipe is closed leads to a 318 * EVFILT_WRITE event with EV_EOF set. 319 */ 320 321 ATF_REQUIRE(kevent(kq, kev, 2, kev, 2, NULL) == 2); 322 ATF_REQUIRE((kev[0].flags & EV_ERROR) != 0); 323 ATF_REQUIRE(kev[0].data == 0); 324 ATF_REQUIRE((kev[1].flags & EV_ERROR) != 0); 325 ATF_REQUIRE(kev[1].data == 0); 326 327 bytes = 0; 328 c = 0; 329 while ((n = write(p[1], &c, 1)) == 1) 330 bytes++; 331 ATF_REQUIRE(n < 0); 332 ATF_REQUIRE(errno == EAGAIN || errno == EWOULDBLOCK); 333 334 ATF_REQUIRE(close(p[1]) == 0); 335 336 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev), 337 &(struct timespec){ 0, 0 }) == 2); 338 339 ATF_REQUIRE(kev[0].ident == (uintptr_t)p[0]); 340 ATF_REQUIRE(kev[0].filter == EVFILT_WRITE); 341 ATF_REQUIRE(kev[0].flags == 342 (EV_EOF | EV_CLEAR | EV_ONESHOT | EV_RECEIPT)); 343 ATF_REQUIRE(kev[0].fflags == 0); 344 ATF_REQUIRE(kev[0].data > 0); 345 ATF_REQUIRE(kev[0].udata == 0); 346 347 ATF_REQUIRE(kev[1].ident == (uintptr_t)p[0]); 348 ATF_REQUIRE(kev[1].filter == EVFILT_READ); 349 ATF_REQUIRE(kev[1].flags == (EV_EOF | EV_CLEAR | EV_RECEIPT)); 350 ATF_REQUIRE(kev[1].fflags == 0); 351 ATF_REQUIRE(kev[1].data == bytes); 352 ATF_REQUIRE(kev[1].udata == 0); 353 354 ATF_REQUIRE(close(kq) == 0); 355 ATF_REQUIRE(close(p[0]) == 0); 356 } 357 358 ATF_TP_ADD_TCS(tp) 359 { 360 ATF_TP_ADD_TC(tp, pipe_kqueue__write_end); 361 ATF_TP_ADD_TC(tp, pipe_kqueue__closed_read_end); 362 ATF_TP_ADD_TC(tp, pipe_kqueue__closed_read_end_register_before_close); 363 ATF_TP_ADD_TC(tp, pipe_kqueue__closed_write_end); 364 ATF_TP_ADD_TC(tp, pipe_kqueue__closed_write_end_register_before_close); 365 366 return atf_no_error(); 367 } 368