]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tests/sys/fifo/fifo_kqueue.c
zfs: merge openzfs/zfs@a4bf6baae
[FreeBSD/FreeBSD.git] / tests / sys / fifo / fifo_kqueue.c
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);
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);
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);
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);
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 }