xref: /netbsd-src/tests/lib/libc/sys/t_poll.c (revision 5de7d31bd2441784bc14a9fce6877163bff6f1e2)
1 /*	$NetBSD: t_poll.c,v 1.8 2021/10/02 17:32:55 thorpej Exp $	*/
2 
3 /*-
4  * Copyright (c) 2011 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Matthias Scheler.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/stat.h>
33 #include <sys/time.h>
34 #include <sys/wait.h>
35 
36 #include <atf-c.h>
37 #include <errno.h>
38 #include <fcntl.h>
39 #include <paths.h>
40 #include <poll.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <signal.h>
44 #include <unistd.h>
45 
46 static int desc;
47 
48 static void
child1(void)49 child1(void)
50 {
51 	struct pollfd pfd;
52 
53 	pfd.fd = desc;
54 	pfd.events = POLLIN | POLLHUP | POLLOUT;
55 
56 	(void)poll(&pfd, 1, 2000);
57 	(void)printf("child1 exit\n");
58 }
59 
60 static void
child2(void)61 child2(void)
62 {
63 	struct pollfd pfd;
64 
65 	pfd.fd = desc;
66 	pfd.events = POLLIN | POLLHUP | POLLOUT;
67 
68 	(void)sleep(1);
69 	(void)poll(&pfd, 1, INFTIM);
70 	(void)printf("child2 exit\n");
71 }
72 
73 static void
child3(void)74 child3(void)
75 {
76 	struct pollfd pfd;
77 
78 	(void)sleep(5);
79 
80 	pfd.fd = desc;
81 	pfd.events = POLLIN | POLLHUP | POLLOUT;
82 
83 	(void)poll(&pfd, 1, INFTIM);
84 	(void)printf("child3 exit\n");
85 }
86 
87 ATF_TC(3way);
88 ATF_TC_HEAD(3way, tc)
89 {
90 	atf_tc_set_md_var(tc, "timeout", "15");
91 	atf_tc_set_md_var(tc, "descr",
92 	    "Check for 3-way collision for descriptor. First child comes "
93 	    "and polls on descriptor, second child comes and polls, first "
94 	    "child times out and exits, third child comes and polls. When "
95 	    "the wakeup event happens, the two remaining children should "
96 	    "both be awaken. (kern/17517)");
97 }
98 
99 ATF_TC_BODY(3way, tc)
100 {
101 	int pf[2];
102 	int status, i;
103 	pid_t pid;
104 
105 	pipe(pf);
106 	desc = pf[0];
107 
108 	pid = fork();
109 	ATF_REQUIRE(pid >= 0);
110 
111 	if (pid == 0) {
112 		(void)close(pf[1]);
113 		child1();
114 		_exit(0);
115 		/* NOTREACHED */
116 	}
117 
118 	pid = fork();
119 	ATF_REQUIRE(pid >= 0);
120 
121 	if (pid == 0) {
122 		(void)close(pf[1]);
123 		child2();
124 		_exit(0);
125 		/* NOTREACHED */
126 	}
127 
128 	pid = fork();
129 	ATF_REQUIRE( pid >= 0);
130 
131 	if (pid == 0) {
132 		(void)close(pf[1]);
133 		child3();
134 		_exit(0);
135 		/* NOTREACHED */
136 	}
137 
138 	(void)sleep(10);
139 
140 	(void)printf("parent write\n");
141 
142 	ATF_REQUIRE(write(pf[1], "konec\n", 6) == 6);
143 
144 	for(i = 0; i < 3; ++i)
145 		(void)wait(&status);
146 
147 	(void)printf("parent terminated\n");
148 }
149 
150 ATF_TC(basic);
ATF_TC_HEAD(basic,tc)151 ATF_TC_HEAD(basic, tc)
152 {
153 	atf_tc_set_md_var(tc, "timeout", "10");
154 	atf_tc_set_md_var(tc, "descr",
155 	    "Basis functionality test for poll(2)");
156 }
157 
ATF_TC_BODY(basic,tc)158 ATF_TC_BODY(basic, tc)
159 {
160 	int fds[2];
161 	struct pollfd pfds[2];
162 	int ret;
163 
164 	ATF_REQUIRE_EQ(pipe(fds), 0);
165 
166 	pfds[0].fd = fds[0];
167 	pfds[0].events = POLLIN;
168 	pfds[1].fd = fds[1];
169 	pfds[1].events = POLLOUT;
170 
171 	/*
172 	 * Check that we get a timeout waiting for data on the read end
173 	 * of our pipe.
174 	 */
175 	pfds[0].revents = -1;
176 	pfds[1].revents = -1;
177 	ATF_REQUIRE_EQ_MSG(ret = poll(&pfds[0], 1, 1), 0,
178 	    "got: %d", ret);
179 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
180 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, -1, "got: %d", pfds[1].revents);
181 
182 	/* Check that the write end of the pipe as reported as ready. */
183 	pfds[0].revents = -1;
184 	pfds[1].revents = -1;
185 	ATF_REQUIRE_EQ_MSG(ret = poll(&pfds[1], 1, 1), 1,
186 	    "got: %d", ret);
187 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, -1, "got: %d", pfds[0].revents);
188 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",\
189 	    pfds[1].revents);
190 
191 	/* Check that only the write end of the pipe as reported as ready. */
192 	pfds[0].revents = -1;
193 	pfds[1].revents = -1;
194 	ATF_REQUIRE_EQ_MSG(ret = poll(pfds, 2, 1), 1,
195 	    "got: %d", ret);
196 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
197 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
198 	    pfds[1].revents);
199 
200 	/* Write data to our pipe. */
201 	ATF_REQUIRE_EQ(write(fds[1], "", 1), 1);
202 
203 	/* Check that both ends of our pipe are reported as ready. */
204 	pfds[0].revents = -1;
205 	pfds[1].revents = -1;
206 	ATF_REQUIRE_EQ_MSG(ret = poll(pfds, 2, 1), 2,
207 	    "got: %d", ret);
208 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, POLLIN, "got: %d",
209 	    pfds[0].revents);
210 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
211 	    pfds[1].revents);
212 
213 	ATF_REQUIRE_EQ(close(fds[0]), 0);
214 	ATF_REQUIRE_EQ(close(fds[1]), 0);
215 }
216 
217 ATF_TC(err);
ATF_TC_HEAD(err,tc)218 ATF_TC_HEAD(err, tc)
219 {
220 	atf_tc_set_md_var(tc, "descr", "Check errors from poll(2)");
221 }
222 
ATF_TC_BODY(err,tc)223 ATF_TC_BODY(err, tc)
224 {
225 	struct pollfd pfd;
226 	int fd = 0;
227 
228 	pfd.fd = fd;
229 	pfd.events = POLLIN;
230 
231 	errno = 0;
232 	ATF_REQUIRE_ERRNO(EFAULT, poll((struct pollfd *)-1, 1, -1) == -1);
233 
234 	errno = 0;
235 	ATF_REQUIRE_ERRNO(EINVAL, poll(&pfd, 1, -2) == -1);
236 }
237 
238 static const char	fifo_path[] = "pollhup_fifo";
239 
240 static void
fifo_support(void)241 fifo_support(void)
242 {
243 	errno = 0;
244 	if (mkfifo(fifo_path, 0600) == 0) {
245 		ATF_REQUIRE(unlink(fifo_path) == 0);
246 		return;
247 	}
248 
249 	if (errno == EOPNOTSUPP) {
250 		atf_tc_skip("the kernel does not support FIFOs");
251 	} else {
252 		atf_tc_fail("mkfifo(2) failed");
253 	}
254 }
255 
256 ATF_TC_WITH_CLEANUP(fifo_inout);
ATF_TC_HEAD(fifo_inout,tc)257 ATF_TC_HEAD(fifo_inout, tc)
258 {
259 	atf_tc_set_md_var(tc, "descr",
260 	    "Check POLLIN/POLLOUT behavior with fifos");
261 }
262 
ATF_TC_BODY(fifo_inout,tc)263 ATF_TC_BODY(fifo_inout, tc)
264 {
265 	struct pollfd pfd[2];
266 	char *buf;
267 	int rfd, wfd;
268 	long pipe_buf;
269 
270 	fifo_support();
271 
272 	ATF_REQUIRE(mkfifo(fifo_path, 0600) == 0);
273 	ATF_REQUIRE((rfd = open(fifo_path, O_RDONLY | O_NONBLOCK)) >= 0);
274 	ATF_REQUIRE((wfd = open(fifo_path, O_WRONLY | O_NONBLOCK)) >= 0);
275 
276 	/* Get the maximum atomic pipe write size. */
277 	pipe_buf = fpathconf(wfd, _PC_PIPE_BUF);
278 	ATF_REQUIRE(pipe_buf > 1);
279 
280 	buf = malloc(pipe_buf);
281 	ATF_REQUIRE(buf != NULL);
282 
283 	memset(&pfd, 0, sizeof(pfd));
284 	pfd[0].fd = rfd;
285 	pfd[0].events = POLLIN | POLLRDNORM;
286 	pfd[1].fd = wfd;
287 	pfd[1].events = POLLOUT | POLLWRNORM;
288 
289 	/* We expect the FIFO to be writable but not readable. */
290 	ATF_REQUIRE(poll(pfd, 2, 0) == 1);
291 	ATF_REQUIRE(pfd[0].revents == 0);
292 	ATF_REQUIRE(pfd[1].revents == (POLLOUT | POLLWRNORM));
293 
294 	/* Write a single byte of data into the FIFO. */
295 	ATF_REQUIRE(write(wfd, buf, 1) == 1);
296 
297 	/* We expect the FIFO to be readable and writable. */
298 	ATF_REQUIRE(poll(pfd, 2, 0) == 2);
299 	ATF_REQUIRE(pfd[0].revents == (POLLIN | POLLRDNORM));
300 	ATF_REQUIRE(pfd[1].revents == (POLLOUT | POLLWRNORM));
301 
302 	/* Read that single byte back out. */
303 	ATF_REQUIRE(read(rfd, buf, 1) == 1);
304 
305 	/*
306 	 * Write data into the FIFO until it is full, which is
307 	 * defined as insufficient buffer space to hold a the
308 	 * maximum atomic pipe write size.
309 	 */
310 	while (write(wfd, buf, pipe_buf) != -1) {
311 		continue;
312 	}
313 	ATF_REQUIRE(errno == EAGAIN);
314 
315 	/* We expect the FIFO to be readble but not writable. */
316 	ATF_REQUIRE(poll(pfd, 2, 0) == 1);
317 	ATF_REQUIRE(pfd[0].revents == (POLLIN | POLLRDNORM));
318 	ATF_REQUIRE(pfd[1].revents == 0);
319 
320 	/* Read a single byte of data from the FIFO. */
321 	ATF_REQUIRE(read(rfd, buf, 1) == 1);
322 
323 	/*
324 	 * Because we have read only a single byte out, there will
325 	 * be insufficient space for a pipe_buf-sized message, so
326 	 * the FIFO should still not be writable.
327 	 */
328 	ATF_REQUIRE(poll(pfd, 2, 0) == 1);
329 	ATF_REQUIRE(pfd[0].revents == (POLLIN | POLLRDNORM));
330 	ATF_REQUIRE(pfd[1].revents == 0);
331 
332 	/*
333 	 * Now read enough so that exactly pipe_buf space should
334 	 * be available.  The FIFO should be writable after that.
335 	 * N.B. we don't care if it's readable at this point.
336 	 */
337 	ATF_REQUIRE(read(rfd, buf, pipe_buf - 1) == pipe_buf - 1);
338 	ATF_REQUIRE(poll(pfd, 2, 0) >= 1);
339 	ATF_REQUIRE(pfd[1].revents == (POLLOUT | POLLWRNORM));
340 
341 	/*
342 	 * Now read all of the data out of the FIFO and ensure that
343 	 * we get back to the initial state.
344 	 */
345 	while (read(rfd, buf, pipe_buf) != -1) {
346 		continue;
347 	}
348 	ATF_REQUIRE(errno == EAGAIN);
349 
350 	ATF_REQUIRE(poll(pfd, 2, 0) == 1);
351 	ATF_REQUIRE(pfd[0].revents == 0);
352 	ATF_REQUIRE(pfd[1].revents == (POLLOUT | POLLWRNORM));
353 
354 	(void)close(wfd);
355 	(void)close(rfd);
356 }
357 
ATF_TC_CLEANUP(fifo_inout,tc)358 ATF_TC_CLEANUP(fifo_inout, tc)
359 {
360 	(void)unlink(fifo_path);
361 }
362 
363 ATF_TC_WITH_CLEANUP(fifo_hup1);
ATF_TC_HEAD(fifo_hup1,tc)364 ATF_TC_HEAD(fifo_hup1, tc)
365 {
366 	atf_tc_set_md_var(tc, "descr",
367 	    "Check POLLHUP behavior with fifos [1]");
368 }
369 
ATF_TC_BODY(fifo_hup1,tc)370 ATF_TC_BODY(fifo_hup1, tc)
371 {
372 	struct pollfd pfd;
373 	int rfd, wfd;
374 
375 	fifo_support();
376 
377 	ATF_REQUIRE(mkfifo(fifo_path, 0600) == 0);
378 	ATF_REQUIRE((rfd = open(fifo_path, O_RDONLY | O_NONBLOCK)) >= 0);
379 	ATF_REQUIRE((wfd = open(fifo_path, O_WRONLY)) >= 0);
380 
381 	memset(&pfd, 0, sizeof(pfd));
382 	pfd.fd = rfd;
383 	pfd.events = POLLIN;
384 
385 	(void)close(wfd);
386 
387 	ATF_REQUIRE(poll(&pfd, 1, 0) == 1);
388 	ATF_REQUIRE((pfd.revents & POLLHUP) != 0);
389 
390 	/*
391 	 * Check that POLLHUP is cleared when a writer re-connects.
392 	 * Since the writer will not put any data into the FIFO, we
393 	 * expect no events.
394 	 */
395 	memset(&pfd, 0, sizeof(pfd));
396 	pfd.fd = rfd;
397 	pfd.events = POLLIN;
398 
399 	ATF_REQUIRE((wfd = open(fifo_path, O_WRONLY)) >= 0);
400 	ATF_REQUIRE(poll(&pfd, 1, 0) == 0);
401 }
402 
ATF_TC_CLEANUP(fifo_hup1,tc)403 ATF_TC_CLEANUP(fifo_hup1, tc)
404 {
405 	(void)unlink(fifo_path);
406 }
407 
408 ATF_TC_WITH_CLEANUP(fifo_hup2);
ATF_TC_HEAD(fifo_hup2,tc)409 ATF_TC_HEAD(fifo_hup2, tc)
410 {
411 	atf_tc_set_md_var(tc, "descr",
412 	    "Check POLLHUP behavior with fifos [2]");
413 }
414 
ATF_TC_BODY(fifo_hup2,tc)415 ATF_TC_BODY(fifo_hup2, tc)
416 {
417 	struct pollfd pfd;
418 	int rfd, wfd;
419 	pid_t pid;
420 	struct timespec ts1, ts2;
421 
422 	fifo_support();
423 
424 	ATF_REQUIRE(mkfifo(fifo_path, 0600) == 0);
425 	ATF_REQUIRE((rfd = open(fifo_path, O_RDONLY | O_NONBLOCK)) >= 0);
426 	ATF_REQUIRE((wfd = open(fifo_path, O_WRONLY)) >= 0);
427 
428 	memset(&pfd, 0, sizeof(pfd));
429 	pfd.fd = rfd;
430 	pfd.events = POLLIN;
431 
432 	pid = fork();
433 	ATF_REQUIRE(pid >= 0);
434 
435 	if (pid == 0) {
436 		(void)close(rfd);
437 		sleep(5);
438 		(void)close(wfd);
439 		_exit(0);
440 	}
441 	(void)close(wfd);
442 
443 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ts1) == 0);
444 	ATF_REQUIRE(poll(&pfd, 1, INFTIM) == 1);
445 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ts2) == 0);
446 
447 	/* Make sure at least a couple of seconds have elapsed. */
448 	ATF_REQUIRE(ts2.tv_sec - ts1.tv_sec >= 2);
449 
450 	ATF_REQUIRE((pfd.revents & POLLHUP) != 0);
451 }
452 
ATF_TC_CLEANUP(fifo_hup2,tc)453 ATF_TC_CLEANUP(fifo_hup2, tc)
454 {
455 	(void)unlink(fifo_path);
456 }
457 
ATF_TP_ADD_TCS(tp)458 ATF_TP_ADD_TCS(tp)
459 {
460 
461 	ATF_TP_ADD_TC(tp, 3way);
462 	ATF_TP_ADD_TC(tp, basic);
463 	ATF_TP_ADD_TC(tp, err);
464 
465 	ATF_TP_ADD_TC(tp, fifo_inout);
466 	ATF_TP_ADD_TC(tp, fifo_hup1);
467 	ATF_TP_ADD_TC(tp, fifo_hup2);
468 
469 	return atf_no_error();
470 }
471