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