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