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