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