xref: /freebsd/tests/sys/fifo/fifo_kqueue.c (revision 6f63e88c0166ed3e5f2805a9e667c7d24d304cf1)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
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(fifo_kqueue__writes);
47 ATF_TC_BODY(fifo_kqueue__writes, tc)
48 {
49 	int p[2] = { -1, -1 };
50 
51 	ATF_REQUIRE(mkfifo("testfifo", 0600) == 0);
52 
53 	ATF_REQUIRE((p[0] = open("testfifo",
54 	    O_RDONLY | O_CLOEXEC | O_NONBLOCK)) >= 0);
55 	ATF_REQUIRE((p[1] = open("testfifo",
56 	    O_WRONLY | O_CLOEXEC | O_NONBLOCK)) >= 0);
57 
58 	int kq = kqueue();
59 	ATF_REQUIRE(kq >= 0);
60 
61 	struct kevent kev[32];
62 	EV_SET(&kev[0], p[1], EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, 0);
63 	EV_SET(&kev[1], p[1], EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, 0);
64 
65 	ATF_REQUIRE(kevent(kq, kev, 2, NULL, 0, NULL) == 0);
66 
67 	/* A new writer should immediately get a EVFILT_WRITE event. */
68 
69 	ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
70 	    &(struct timespec) { 0, 0 }) == 1);
71 	ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]);
72 	ATF_REQUIRE(kev[0].filter == EVFILT_WRITE);
73 	ATF_REQUIRE(kev[0].flags == EV_CLEAR);
74 	ATF_REQUIRE(kev[0].fflags == 0);
75 	ATF_REQUIRE(kev[0].data == 16384);
76 	ATF_REQUIRE(kev[0].udata == 0);
77 
78 	/* Filling up the pipe should make the EVFILT_WRITE disappear. */
79 
80 	char c = 0;
81 	ssize_t r;
82 	while ((r = write(p[1], &c, 1)) == 1) {
83 	}
84 	ATF_REQUIRE(r < 0);
85 	ATF_REQUIRE(errno == EAGAIN || errno == EWOULDBLOCK);
86 
87 	ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
88 	    &(struct timespec) { 0, 0 }) == 0);
89 
90 	/* Reading (PIPE_BUF - 1) bytes will not trigger a EVFILT_WRITE yet. */
91 
92 	for (int i = 0; i < PIPE_BUF - 1; ++i) {
93 		ATF_REQUIRE(read(p[0], &c, 1) == 1);
94 	}
95 
96 	ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
97 	    &(struct timespec) { 0, 0 }) == 0);
98 
99 	/* Reading one additional byte triggers the EVFILT_WRITE. */
100 
101 	ATF_REQUIRE(read(p[0], &c, 1) == 1);
102 
103 	ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
104 	    &(struct timespec) { 0, 0 }) == 1);
105 	ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]);
106 	ATF_REQUIRE(kev[0].filter == EVFILT_WRITE);
107 	ATF_REQUIRE(kev[0].flags == EV_CLEAR);
108 	ATF_REQUIRE(kev[0].fflags == 0);
109 	ATF_REQUIRE(kev[0].data == PIPE_BUF);
110 	ATF_REQUIRE(kev[0].udata == 0);
111 
112 	/*
113 	 * Reading another byte triggers the EVFILT_WRITE again with a changed
114 	 * 'data' field.
115 	 */
116 
117 	ATF_REQUIRE(read(p[0], &c, 1) == 1);
118 
119 	ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
120 	    &(struct timespec) { 0, 0 }) == 1);
121 	ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]);
122 	ATF_REQUIRE(kev[0].filter == EVFILT_WRITE);
123 	ATF_REQUIRE(kev[0].flags == EV_CLEAR);
124 	ATF_REQUIRE(kev[0].fflags == 0);
125 	ATF_REQUIRE(kev[0].data == PIPE_BUF + 1);
126 	ATF_REQUIRE(kev[0].udata == 0);
127 
128 	/*
129 	 * Closing the read end should make a EV_EOF appear but leave the 'data'
130 	 * field unchanged.
131 	 */
132 
133 	ATF_REQUIRE(close(p[0]) == 0);
134 
135 	ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev), NULL) == 1);
136 	ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]);
137 	ATF_REQUIRE(kev[0].filter == EVFILT_WRITE);
138 	ATF_REQUIRE(kev[0].flags == (EV_CLEAR | EV_EOF));
139 	ATF_REQUIRE(kev[0].fflags == 0);
140 	ATF_REQUIRE(kev[0].data == PIPE_BUF + 1);
141 	ATF_REQUIRE(kev[0].udata == 0);
142 
143 	ATF_REQUIRE(close(kq) == 0);
144 	ATF_REQUIRE(close(p[1]) == 0);
145 }
146 
147 ATF_TC_WITHOUT_HEAD(fifo_kqueue__connecting_reader);
148 ATF_TC_BODY(fifo_kqueue__connecting_reader, tc)
149 {
150 	int p[2] = { -1, -1 };
151 
152 	ATF_REQUIRE(mkfifo("testfifo", 0600) == 0);
153 
154 	ATF_REQUIRE((p[0] = open("testfifo",
155 	    O_RDONLY | O_CLOEXEC | O_NONBLOCK)) >= 0);
156 	ATF_REQUIRE((p[1] = open("testfifo",
157 	    O_WRONLY | O_CLOEXEC | O_NONBLOCK)) >= 0);
158 
159 	int kq = kqueue();
160 	ATF_REQUIRE(kq >= 0);
161 
162 	struct kevent kev[32];
163 	EV_SET(&kev[0], p[1], EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, 0);
164 	EV_SET(&kev[1], p[1], EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, 0);
165 
166 	ATF_REQUIRE(kevent(kq, kev, 2, NULL, 0, NULL) == 0);
167 
168 	/* A new writer should immediately get a EVFILT_WRITE event. */
169 
170 	ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
171 	    &(struct timespec) { 0, 0 }) == 1);
172 	ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]);
173 	ATF_REQUIRE(kev[0].filter == EVFILT_WRITE);
174 	ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
175 	    &(struct timespec) { 0, 0 }) == 0);
176 
177 	/*
178 	 * Filling the pipe, reading (PIPE_BUF + 1) bytes, then closing the
179 	 * read end leads to a EVFILT_WRITE with EV_EOF set.
180 	 */
181 
182 	char c = 0;
183 	ssize_t r;
184 	while ((r = write(p[1], &c, 1)) == 1) {
185 	}
186 	ATF_REQUIRE(r < 0);
187 	ATF_REQUIRE(errno == EAGAIN || errno == EWOULDBLOCK);
188 
189 	for (int i = 0; i < PIPE_BUF + 1; ++i) {
190 		ATF_REQUIRE(read(p[0], &c, 1) == 1);
191 	}
192 
193 	ATF_REQUIRE(close(p[0]) == 0);
194 
195 	ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev), NULL) == 1);
196 	ATF_REQUIRE(kev[0].filter == EVFILT_WRITE);
197 	ATF_REQUIRE((kev[0].flags & EV_EOF) != 0);
198 	ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
199 	    &(struct timespec) { 0, 0 }) == 0);
200 
201 	/* Opening the reader again must trigger the EVFILT_WRITE. */
202 
203 	ATF_REQUIRE((p[0] = open("testfifo",
204 	    O_RDONLY | O_CLOEXEC | O_NONBLOCK)) >= 0);
205 
206 	r = kevent(kq, NULL, 0, kev, nitems(kev), &(struct timespec) { 1, 0 });
207 	ATF_REQUIRE(r == 1);
208 	ATF_REQUIRE(kev[0].ident == (uintptr_t)p[1]);
209 	ATF_REQUIRE(kev[0].filter == EVFILT_WRITE);
210 	ATF_REQUIRE(kev[0].flags == EV_CLEAR);
211 	ATF_REQUIRE(kev[0].fflags == 0);
212 	ATF_REQUIRE(kev[0].data == PIPE_BUF + 1);
213 	ATF_REQUIRE(kev[0].udata == 0);
214 	ATF_REQUIRE(kevent(kq, NULL, 0, kev, nitems(kev),
215 	    &(struct timespec) { 0, 0 }) == 0);
216 
217 	ATF_REQUIRE(close(kq) == 0);
218 	ATF_REQUIRE(close(p[0]) == 0);
219 	ATF_REQUIRE(close(p[1]) == 0);
220 }
221 
222 ATF_TC_WITHOUT_HEAD(fifo_kqueue__reads);
223 ATF_TC_BODY(fifo_kqueue__reads, tc)
224 {
225 	int p[2] = { -1, -1 };
226 
227 	ATF_REQUIRE(mkfifo("testfifo", 0600) == 0);
228 
229 	ATF_REQUIRE((p[0] = open("testfifo",
230 	    O_RDONLY | O_CLOEXEC | O_NONBLOCK)) >= 0);
231 	ATF_REQUIRE((p[1] = open("testfifo",
232 	    O_WRONLY | O_CLOEXEC | O_NONBLOCK)) >= 0);
233 
234 	/* Check that EVFILT_READ behaves sensibly on a FIFO reader. */
235 
236 	char c = 0;
237 	ssize_t r;
238 	while ((r = write(p[1], &c, 1)) == 1) {
239 	}
240 	ATF_REQUIRE(r < 0);
241 	ATF_REQUIRE(errno == EAGAIN || errno == EWOULDBLOCK);
242 
243 	for (int i = 0; i < PIPE_BUF + 1; ++i) {
244 		ATF_REQUIRE(read(p[0], &c, 1) == 1);
245 	}
246 
247 	int kq = kqueue();
248 	ATF_REQUIRE(kq >= 0);
249 
250 	struct kevent kev[32];
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 == 65023);
262 	ATF_REQUIRE(kev[0].udata == 0);
263 
264 	while ((r = read(p[0], &c, 1)) == 1) {
265 	}
266 	ATF_REQUIRE(r < 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);
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);
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 
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