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(fifo_kqueue__writes);
ATF_TC_BODY(fifo_kqueue__writes,tc)44 ATF_TC_BODY(fifo_kqueue__writes, tc)
45 {
46 int p[2] = { -1, -1 };
47
48 ATF_REQUIRE(mkfifo("testfifo", 0600) == 0);
49
50 ATF_REQUIRE((p[0] = open("testfifo",
51 O_RDONLY | O_CLOEXEC | O_NONBLOCK)) >= 0);
52 ATF_REQUIRE((p[1] = open("testfifo",
53 O_WRONLY | O_CLOEXEC | O_NONBLOCK)) >= 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 EV_SET(&kev[1], p[1], EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, 0);
61
62 ATF_REQUIRE(kevent(kq, kev, 2, NULL, 0, NULL) == 0);
63
64 /* A new writer should immediately get a EVFILT_WRITE event. */
65
66 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
67 &(struct timespec) { 0, 0 }) == 1);
68 ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]);
69 ATF_REQUIRE(kev[0].filter == EVFILT_WRITE);
70 ATF_REQUIRE(kev[0].flags == EV_CLEAR);
71 ATF_REQUIRE(kev[0].fflags == 0);
72 ATF_REQUIRE(kev[0].data == 16384);
73 ATF_REQUIRE(kev[0].udata == 0);
74
75 /* Filling up the pipe should make the EVFILT_WRITE disappear. */
76
77 char c = 0;
78 ssize_t r;
79 while ((r = write(p[1], &c, 1)) == 1) {
80 }
81 ATF_REQUIRE(r < 0);
82 ATF_REQUIRE(errno == EAGAIN || errno == EWOULDBLOCK);
83
84 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
85 &(struct timespec) { 0, 0 }) == 0);
86
87 /* Reading (PIPE_BUF - 1) bytes will not trigger a EVFILT_WRITE yet. */
88
89 for (int i = 0; i < PIPE_BUF - 1; ++i) {
90 ATF_REQUIRE(read(p[0], &c, 1) == 1);
91 }
92
93 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
94 &(struct timespec) { 0, 0 }) == 0);
95
96 /* Reading one additional byte triggers the EVFILT_WRITE. */
97
98 ATF_REQUIRE(read(p[0], &c, 1) == 1);
99
100 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
101 &(struct timespec) { 0, 0 }) == 1);
102 ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]);
103 ATF_REQUIRE(kev[0].filter == EVFILT_WRITE);
104 ATF_REQUIRE(kev[0].flags == EV_CLEAR);
105 ATF_REQUIRE(kev[0].fflags == 0);
106 ATF_REQUIRE(kev[0].data == PIPE_BUF);
107 ATF_REQUIRE(kev[0].udata == 0);
108
109 /*
110 * Reading another byte triggers the EVFILT_WRITE again with a changed
111 * 'data' field.
112 */
113
114 ATF_REQUIRE(read(p[0], &c, 1) == 1);
115
116 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
117 &(struct timespec) { 0, 0 }) == 1);
118 ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]);
119 ATF_REQUIRE(kev[0].filter == EVFILT_WRITE);
120 ATF_REQUIRE(kev[0].flags == EV_CLEAR);
121 ATF_REQUIRE(kev[0].fflags == 0);
122 ATF_REQUIRE(kev[0].data == PIPE_BUF + 1);
123 ATF_REQUIRE(kev[0].udata == 0);
124
125 /*
126 * Closing the read end should make a EV_EOF appear but leave the 'data'
127 * field unchanged.
128 */
129
130 ATF_REQUIRE(close(p[0]) == 0);
131
132 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev), NULL) == 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));
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(fifo_kqueue__connecting_reader);
ATF_TC_BODY(fifo_kqueue__connecting_reader,tc)145 ATF_TC_BODY(fifo_kqueue__connecting_reader, tc)
146 {
147 int p[2] = { -1, -1 };
148
149 ATF_REQUIRE(mkfifo("testfifo", 0600) == 0);
150
151 ATF_REQUIRE((p[0] = open("testfifo",
152 O_RDONLY | O_CLOEXEC | O_NONBLOCK)) >= 0);
153 ATF_REQUIRE((p[1] = open("testfifo",
154 O_WRONLY | O_CLOEXEC | O_NONBLOCK)) >= 0);
155
156 int kq = kqueue();
157 ATF_REQUIRE(kq >= 0);
158
159 struct kevent kev[32];
160 EV_SET(&kev[0], p[1], EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, 0);
161 EV_SET(&kev[1], p[1], EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, 0);
162
163 ATF_REQUIRE(kevent(kq, kev, 2, NULL, 0, NULL) == 0);
164
165 /* A new writer should immediately get a EVFILT_WRITE event. */
166
167 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
168 &(struct timespec) { 0, 0 }) == 1);
169 ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]);
170 ATF_REQUIRE(kev[0].filter == EVFILT_WRITE);
171 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
172 &(struct timespec) { 0, 0 }) == 0);
173
174 /*
175 * Filling the pipe, reading (PIPE_BUF + 1) bytes, then closing the
176 * read end leads to a EVFILT_WRITE with EV_EOF set.
177 */
178
179 char c = 0;
180 ssize_t r;
181 while ((r = write(p[1], &c, 1)) == 1) {
182 }
183 ATF_REQUIRE(r < 0);
184 ATF_REQUIRE(errno == EAGAIN || errno == EWOULDBLOCK);
185
186 for (int i = 0; i < PIPE_BUF + 1; ++i) {
187 ATF_REQUIRE(read(p[0], &c, 1) == 1);
188 }
189
190 ATF_REQUIRE(close(p[0]) == 0);
191
192 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev), NULL) == 1);
193 ATF_REQUIRE(kev[0].filter == EVFILT_WRITE);
194 ATF_REQUIRE((kev[0].flags & EV_EOF) != 0);
195 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
196 &(struct timespec) { 0, 0 }) == 0);
197
198 /* Opening the reader again must trigger the EVFILT_WRITE. */
199
200 ATF_REQUIRE((p[0] = open("testfifo",
201 O_RDONLY | O_CLOEXEC | O_NONBLOCK)) >= 0);
202
203 r = kevent(kq, NULL, 0, kev, nitems(kev), &(struct timespec) { 1, 0 });
204 ATF_REQUIRE(r == 1);
205 ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]);
206 ATF_REQUIRE(kev[0].filter == EVFILT_WRITE);
207 ATF_REQUIRE(kev[0].flags == EV_CLEAR);
208 ATF_REQUIRE(kev[0].fflags == 0);
209 ATF_REQUIRE(kev[0].data == PIPE_BUF + 1);
210 ATF_REQUIRE(kev[0].udata == 0);
211 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
212 &(struct timespec) { 0, 0 }) == 0);
213
214 ATF_REQUIRE(close(kq) == 0);
215 ATF_REQUIRE(close(p[0]) == 0);
216 ATF_REQUIRE(close(p[1]) == 0);
217 }
218
219 /* Check that EVFILT_READ behaves sensibly on a FIFO reader. */
220 ATF_TC_WITHOUT_HEAD(fifo_kqueue__reads);
ATF_TC_BODY(fifo_kqueue__reads,tc)221 ATF_TC_BODY(fifo_kqueue__reads, tc)
222 {
223 struct kevent kev[32];
224 ssize_t bytes, i, n;
225 int kq, p[2];
226 char c;
227
228 ATF_REQUIRE(mkfifo("testfifo", 0600) == 0);
229
230 ATF_REQUIRE((p[0] = open("testfifo",
231 O_RDONLY | O_CLOEXEC | O_NONBLOCK)) >= 0);
232 ATF_REQUIRE((p[1] = open("testfifo",
233 O_WRONLY | O_CLOEXEC | O_NONBLOCK)) >= 0);
234
235 bytes = 0;
236 c = 0;
237 while ((n = write(p[1], &c, 1)) == 1)
238 bytes++;
239 ATF_REQUIRE(n < 0);
240 ATF_REQUIRE(errno == EAGAIN || errno == EWOULDBLOCK);
241 ATF_REQUIRE(bytes > 1);
242
243 for (i = 0; i < bytes / 2; i++)
244 ATF_REQUIRE(read(p[0], &c, 1) == 1);
245 bytes -= i;
246
247 kq = kqueue();
248 ATF_REQUIRE(kq >= 0);
249
250 EV_SET(&kev[0], p[0], EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, 0);
251
252 ATF_REQUIRE(kevent(kq, kev, 1, NULL, 0, NULL) == 0);
253
254 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
255 &(struct timespec){ 0, 0 }) == 1);
256 ATF_REQUIRE(kev[0].ident == (uintptr_t)p[0]);
257 ATF_REQUIRE(kev[0].filter == EVFILT_READ);
258 ATF_REQUIRE(kev[0].flags == EV_CLEAR);
259 ATF_REQUIRE(kev[0].fflags == 0);
260 ATF_REQUIRE(kev[0].data == bytes);
261 ATF_REQUIRE(kev[0].udata == 0);
262
263 while (bytes-- > 0)
264 ATF_REQUIRE(read(p[0], &c, 1) == 1);
265 n = read(p[0], &c, 1);
266 ATF_REQUIRE(n < 0);
267 ATF_REQUIRE(errno == EAGAIN || errno == EWOULDBLOCK);
268
269 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
270 &(struct timespec) { 0, 0 }) == 0);
271
272 ATF_REQUIRE(close(kq) == 0);
273 ATF_REQUIRE(close(p[0]) == 0);
274 ATF_REQUIRE(close(p[1]) == 0);
275 }
276
277 ATF_TC_WITHOUT_HEAD(fifo_kqueue__read_eof_wakeups);
ATF_TC_BODY(fifo_kqueue__read_eof_wakeups,tc)278 ATF_TC_BODY(fifo_kqueue__read_eof_wakeups, tc)
279 {
280 int p[2] = { -1, -1 };
281
282 ATF_REQUIRE(mkfifo("testfifo", 0600) == 0);
283
284 ATF_REQUIRE((p[0] = open("testfifo",
285 O_RDONLY | O_CLOEXEC | O_NONBLOCK)) >= 0);
286 ATF_REQUIRE((p[1] = open("testfifo",
287 O_WRONLY | O_CLOEXEC | O_NONBLOCK)) >= 0);
288
289 int kq = kqueue();
290 ATF_REQUIRE(kq >= 0);
291
292 struct kevent kev[32];
293
294 EV_SET(&kev[0], p[0], EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, 0);
295 ATF_REQUIRE(kevent(kq, kev, 1, NULL, 0, NULL) == 0);
296
297 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
298 &(struct timespec) { 0, 0 }) == 0);
299
300 /*
301 * Closing the writer must trigger a EVFILT_READ edge with EV_EOF set.
302 */
303
304 ATF_REQUIRE(close(p[1]) == 0);
305
306 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
307 &(struct timespec) { 0, 0 }) == 1);
308 ATF_REQUIRE(kev[0].ident == (uintptr_t)p[0]);
309 ATF_REQUIRE(kev[0].filter == EVFILT_READ);
310 ATF_REQUIRE(kev[0].flags == (EV_EOF | EV_CLEAR));
311 ATF_REQUIRE(kev[0].fflags == 0);
312 ATF_REQUIRE(kev[0].data == 0);
313 ATF_REQUIRE(kev[0].udata == 0);
314
315 /*
316 * Trying to read from a closed pipe should not trigger EVFILT_READ
317 * edges.
318 */
319
320 char c;
321 ATF_REQUIRE(read(p[0], &c, 1) == 0);
322
323 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
324 &(struct timespec) { 0, 0 }) == 0);
325
326 ATF_REQUIRE(close(kq) == 0);
327 ATF_REQUIRE(close(p[0]) == 0);
328 }
329
330 ATF_TC_WITHOUT_HEAD(fifo_kqueue__read_eof_state_when_reconnecting);
ATF_TC_BODY(fifo_kqueue__read_eof_state_when_reconnecting,tc)331 ATF_TC_BODY(fifo_kqueue__read_eof_state_when_reconnecting, tc)
332 {
333 int p[2] = { -1, -1 };
334
335 ATF_REQUIRE(mkfifo("testfifo", 0600) == 0);
336
337 ATF_REQUIRE((p[0] = open("testfifo",
338 O_RDONLY | O_CLOEXEC | O_NONBLOCK)) >= 0);
339 ATF_REQUIRE((p[1] = open("testfifo",
340 O_WRONLY | O_CLOEXEC | O_NONBLOCK)) >= 0);
341
342 int kq = kqueue();
343 ATF_REQUIRE(kq >= 0);
344
345 struct kevent kev[32];
346
347 EV_SET(&kev[0], p[0], EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, 0);
348 ATF_REQUIRE(kevent(kq, kev, 1, NULL, 0, NULL) == 0);
349
350 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
351 &(struct timespec) { 0, 0 }) == 0);
352
353 /*
354 * Closing the writer must trigger a EVFILT_READ edge with EV_EOF set.
355 */
356
357 ATF_REQUIRE(close(p[1]) == 0);
358
359 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
360 &(struct timespec) { 0, 0 }) == 1);
361 ATF_REQUIRE(kev[0].ident == (uintptr_t)p[0]);
362 ATF_REQUIRE(kev[0].filter == EVFILT_READ);
363 ATF_REQUIRE(kev[0].flags == (EV_EOF | EV_CLEAR));
364 ATF_REQUIRE(kev[0].fflags == 0);
365 ATF_REQUIRE(kev[0].data == 0);
366 ATF_REQUIRE(kev[0].udata == 0);
367
368 /* A new reader shouldn't see the EOF flag. */
369
370 {
371 int new_reader;
372 ATF_REQUIRE((new_reader = open("testfifo",
373 O_RDONLY | O_CLOEXEC | O_NONBLOCK)) >= 0);
374
375 int new_kq = kqueue();
376 ATF_REQUIRE(new_kq >= 0);
377
378 struct kevent new_kev[32];
379 EV_SET(&new_kev[0], new_reader, EVFILT_READ, EV_ADD | EV_CLEAR,
380 0, 0, 0);
381 ATF_REQUIRE(kevent(new_kq, new_kev, 1, NULL, 0, NULL) == 0);
382
383 ATF_REQUIRE(kevent(new_kq, NULL, 0, new_kev, nitems(new_kev),
384 &(struct timespec) { 0, 0 }) == 0);
385
386 ATF_REQUIRE(close(new_kq) == 0);
387 ATF_REQUIRE(close(new_reader) == 0);
388 }
389
390 /*
391 * Simply reopening the writer does not trigger the EVFILT_READ again --
392 * EV_EOF should be cleared, but there is no data yet so the filter
393 * does not trigger.
394 */
395
396 ATF_REQUIRE((p[1] = open("testfifo",
397 O_WRONLY | O_CLOEXEC | O_NONBLOCK)) >= 0);
398
399 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
400 &(struct timespec) { 0, 0 }) == 0);
401
402 /* Writing a byte should trigger a EVFILT_READ. */
403
404 char c = 0;
405 ATF_REQUIRE(write(p[1], &c, 1) == 1);
406
407 ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
408 &(struct timespec) { 0, 0 }) == 1);
409 ATF_REQUIRE(kev[0].ident == (uintptr_t)p[0]);
410 ATF_REQUIRE(kev[0].filter == EVFILT_READ);
411 ATF_REQUIRE(kev[0].flags == EV_CLEAR);
412 ATF_REQUIRE(kev[0].fflags == 0);
413 ATF_REQUIRE(kev[0].data == 1);
414 ATF_REQUIRE(kev[0].udata == 0);
415
416 ATF_REQUIRE(close(kq) == 0);
417 ATF_REQUIRE(close(p[0]) == 0);
418 ATF_REQUIRE(close(p[1]) == 0);
419 }
420
ATF_TP_ADD_TCS(tp)421 ATF_TP_ADD_TCS(tp)
422 {
423 ATF_TP_ADD_TC(tp, fifo_kqueue__writes);
424 ATF_TP_ADD_TC(tp, fifo_kqueue__connecting_reader);
425 ATF_TP_ADD_TC(tp, fifo_kqueue__reads);
426 ATF_TP_ADD_TC(tp, fifo_kqueue__read_eof_wakeups);
427 ATF_TP_ADD_TC(tp, fifo_kqueue__read_eof_state_when_reconnecting);
428
429 return atf_no_error();
430 }
431