xref: /freebsd/contrib/netbsd-tests/lib/libc/sys/t_poll.c (revision 193d9e768ba63fcfb187cfd17f461f7d41345048)
1 /*	$NetBSD: t_poll.c,v 1.3 2012/03/18 07:00:52 jruoho 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/time.h>
33 #include <sys/wait.h>
34 
35 #include <atf-c.h>
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <paths.h>
39 #include <poll.h>
40 #include <stdio.h>
41 #include <signal.h>
42 #include <unistd.h>
43 
44 static int desc;
45 
46 static void
47 child1(void)
48 {
49 	struct pollfd pfd;
50 
51 	pfd.fd = desc;
52 	pfd.events = POLLIN | POLLHUP | POLLOUT;
53 
54 	(void)poll(&pfd, 1, 2000);
55 	(void)printf("child1 exit\n");
56 }
57 
58 static void
59 child2(void)
60 {
61 	struct pollfd pfd;
62 
63 	pfd.fd = desc;
64 	pfd.events = POLLIN | POLLHUP | POLLOUT;
65 
66 	(void)sleep(1);
67 	(void)poll(&pfd, 1, INFTIM);
68 	(void)printf("child2 exit\n");
69 }
70 
71 static void
72 child3(void)
73 {
74 	struct pollfd pfd;
75 
76 	(void)sleep(5);
77 
78 	pfd.fd = desc;
79 	pfd.events = POLLIN | POLLHUP | POLLOUT;
80 
81 	(void)poll(&pfd, 1, INFTIM);
82 	(void)printf("child3 exit\n");
83 }
84 
85 ATF_TC(poll_3way);
86 ATF_TC_HEAD(poll_3way, tc)
87 {
88 	atf_tc_set_md_var(tc, "timeout", "15");
89 	atf_tc_set_md_var(tc, "descr",
90 	    "Check for 3-way collision for descriptor. First child comes "
91 	    "and polls on descriptor, second child comes and polls, first "
92 	    "child times out and exits, third child comes and polls. When "
93 	    "the wakeup event happens, the two remaining children should "
94 	    "both be awaken. (kern/17517)");
95 }
96 
97 ATF_TC_BODY(poll_3way, tc)
98 {
99 	int pf[2];
100 	int status, i;
101 	pid_t pid;
102 
103 	pipe(pf);
104 	desc = pf[0];
105 
106 	pid = fork();
107 	ATF_REQUIRE(pid >= 0);
108 
109 	if (pid == 0) {
110 		(void)close(pf[1]);
111 		child1();
112 		_exit(0);
113 		/* NOTREACHED */
114 	}
115 
116 	pid = fork();
117 	ATF_REQUIRE(pid >= 0);
118 
119 	if (pid == 0) {
120 		(void)close(pf[1]);
121 		child2();
122 		_exit(0);
123 		/* NOTREACHED */
124 	}
125 
126 	pid = fork();
127 	ATF_REQUIRE( pid >= 0);
128 
129 	if (pid == 0) {
130 		(void)close(pf[1]);
131 		child3();
132 		_exit(0);
133 		/* NOTREACHED */
134 	}
135 
136 	(void)sleep(10);
137 
138 	(void)printf("parent write\n");
139 
140 	ATF_REQUIRE(write(pf[1], "konec\n", 6) == 6);
141 
142 	for(i = 0; i < 3; ++i)
143 		(void)wait(&status);
144 
145 	(void)printf("parent terminated\n");
146 }
147 
148 ATF_TC(poll_basic);
149 ATF_TC_HEAD(poll_basic, tc)
150 {
151 	atf_tc_set_md_var(tc, "timeout", "10");
152 	atf_tc_set_md_var(tc, "descr",
153 	    "Basis functionality test for poll(2)");
154 }
155 
156 ATF_TC_BODY(poll_basic, tc)
157 {
158 	int fds[2];
159 	struct pollfd pfds[2];
160 	int ret;
161 
162 	ATF_REQUIRE_EQ(pipe(fds), 0);
163 
164 	pfds[0].fd = fds[0];
165 	pfds[0].events = POLLIN;
166 	pfds[1].fd = fds[1];
167 	pfds[1].events = POLLOUT;
168 
169 	/*
170 	 * Check that we get a timeout waiting for data on the read end
171 	 * of our pipe.
172 	 */
173 	pfds[0].revents = -1;
174 	pfds[1].revents = -1;
175 	ATF_REQUIRE_EQ_MSG(ret = poll(&pfds[0], 1, 1), 0,
176 	    "got: %d", ret);
177 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
178 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, -1, "got: %d", pfds[1].revents);
179 
180 	/* Check that the write end of the pipe as reported as ready. */
181 	pfds[0].revents = -1;
182 	pfds[1].revents = -1;
183 	ATF_REQUIRE_EQ_MSG(ret = poll(&pfds[1], 1, 1), 1,
184 	    "got: %d", ret);
185 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, -1, "got: %d", pfds[0].revents);
186 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",\
187 	    pfds[1].revents);
188 
189 	/* Check that only the write end of the pipe as reported as ready. */
190 	pfds[0].revents = -1;
191 	pfds[1].revents = -1;
192 	ATF_REQUIRE_EQ_MSG(ret = poll(pfds, 2, 1), 1,
193 	    "got: %d", ret);
194 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
195 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
196 	    pfds[1].revents);
197 
198 	/* Write data to our pipe. */
199 	ATF_REQUIRE_EQ(write(fds[1], "", 1), 1);
200 
201 	/* Check that both ends of our pipe are reported as ready. */
202 	pfds[0].revents = -1;
203 	pfds[1].revents = -1;
204 	ATF_REQUIRE_EQ_MSG(ret = poll(pfds, 2, 1), 2,
205 	    "got: %d", ret);
206 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, POLLIN, "got: %d",
207 	    pfds[0].revents);
208 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
209 	    pfds[1].revents);
210 
211 	ATF_REQUIRE_EQ(close(fds[0]), 0);
212 	ATF_REQUIRE_EQ(close(fds[1]), 0);
213 }
214 
215 ATF_TC(poll_err);
216 ATF_TC_HEAD(poll_err, tc)
217 {
218 	atf_tc_set_md_var(tc, "descr", "Check errors from poll(2)");
219 }
220 
221 ATF_TC_BODY(poll_err, tc)
222 {
223 	struct pollfd pfd;
224 	int fd = 0;
225 
226 	pfd.fd = fd;
227 	pfd.events = POLLIN;
228 
229 	errno = 0;
230 	ATF_REQUIRE_ERRNO(EFAULT, poll((struct pollfd *)-1, 1, -1) == -1);
231 
232 	errno = 0;
233 	ATF_REQUIRE_ERRNO(EINVAL, poll(&pfd, 1, -2) == -1);
234 }
235 
236 #ifndef __FreeBSD__
237 ATF_TC(pollts_basic);
238 ATF_TC_HEAD(pollts_basic, tc)
239 {
240 	atf_tc_set_md_var(tc, "timeout", "10");
241 	atf_tc_set_md_var(tc, "descr",
242 	    "Basis functionality test for pollts(2)");
243 }
244 
245 ATF_TC_BODY(pollts_basic, tc)
246 {
247 	int fds[2];
248 	struct pollfd pfds[2];
249 	struct timespec timeout;
250 	int ret;
251 
252 	ATF_REQUIRE_EQ(pipe(fds), 0);
253 
254 	pfds[0].fd = fds[0];
255 	pfds[0].events = POLLIN;
256 	pfds[1].fd = fds[1];
257 	pfds[1].events = POLLOUT;
258 
259 	/* Use a timeout of 1 second. */
260 	timeout.tv_sec = 1;
261 	timeout.tv_nsec = 0;
262 
263 	/*
264 	 * Check that we get a timeout waiting for data on the read end
265 	 * of our pipe.
266 	 */
267 	pfds[0].revents = -1;
268 	pfds[1].revents = -1;
269 	ATF_REQUIRE_EQ_MSG(ret = pollts(&pfds[0], 1, &timeout, NULL), 0,
270 	    "got: %d", ret);
271 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
272 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, -1, "got: %d", pfds[1].revents);
273 
274 	/* Check that the write end of the pipe as reported as ready. */
275 	pfds[0].revents = -1;
276 	pfds[1].revents = -1;
277 	ATF_REQUIRE_EQ_MSG(ret = pollts(&pfds[1], 1, &timeout, NULL), 1,
278 	    "got: %d", ret);
279 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, -1, "got: %d", pfds[0].revents);
280 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",\
281 	    pfds[1].revents);
282 
283 	/* Check that only the write end of the pipe as reported as ready. */
284 	pfds[0].revents = -1;
285 	pfds[1].revents = -1;
286 	ATF_REQUIRE_EQ_MSG(ret = pollts(pfds, 2, &timeout, NULL), 1,
287 	    "got: %d", ret);
288 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
289 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
290 	    pfds[1].revents);
291 
292 	/* Write data to our pipe. */
293 	ATF_REQUIRE_EQ(write(fds[1], "", 1), 1);
294 
295 	/* Check that both ends of our pipe are reported as ready. */
296 	pfds[0].revents = -1;
297 	pfds[1].revents = -1;
298 	ATF_REQUIRE_EQ_MSG(ret = pollts(pfds, 2, &timeout, NULL), 2,
299 	    "got: %d", ret);
300 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, POLLIN, "got: %d",
301 	    pfds[0].revents);
302 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
303 	    pfds[1].revents);
304 
305 	ATF_REQUIRE_EQ(close(fds[0]), 0);
306 	ATF_REQUIRE_EQ(close(fds[1]), 0);
307 }
308 
309 ATF_TC(pollts_err);
310 ATF_TC_HEAD(pollts_err, tc)
311 {
312 	atf_tc_set_md_var(tc, "descr", "Check errors from pollts(2)");
313 }
314 
315 ATF_TC_BODY(pollts_err, tc)
316 {
317 	struct timespec timeout;
318 	struct pollfd pfd;
319 	int fd = 0;
320 
321 	pfd.fd = fd;
322 	pfd.events = POLLIN;
323 
324 	timeout.tv_sec = 1;
325 	timeout.tv_nsec = 0;
326 
327 	errno = 0;
328 	ATF_REQUIRE_ERRNO(EFAULT, pollts((void *)-1, 1, &timeout, NULL) == -1);
329 
330 	timeout.tv_sec = -1;
331 	timeout.tv_nsec = -1;
332 
333 	errno = 0;
334 	ATF_REQUIRE_ERRNO(EINVAL, pollts(&pfd, 1, &timeout, NULL) == -1);
335 }
336 
337 ATF_TC(pollts_sigmask);
338 ATF_TC_HEAD(pollts_sigmask, tc)
339 {
340 	atf_tc_set_md_var(tc, "timeout", "10");
341 	atf_tc_set_md_var(tc, "descr",
342 	    "Check that pollts(2) restores the signal mask (PR kern/44986)");
343 }
344 
345 ATF_TC_BODY(pollts_sigmask, tc)
346 {
347 	int fd;
348 	struct pollfd pfd;
349 	struct timespec timeout;
350 	sigset_t mask;
351 	int ret;
352 
353 	fd = open(_PATH_DEVNULL, O_RDONLY);
354 	ATF_REQUIRE(fd >= 0);
355 
356 	pfd.fd = fd;
357 	pfd.events = POLLIN;
358 
359 	/* Use a timeout of 1 second. */
360 	timeout.tv_sec = 1;
361 	timeout.tv_nsec = 0;
362 
363 	/* Unblock all signals. */
364 	ATF_REQUIRE_EQ(sigfillset(&mask), 0);
365 	ATF_REQUIRE_EQ(sigprocmask(SIG_UNBLOCK, &mask, NULL), 0);
366 
367 	/*
368 	 * Check that pollts(2) immediately returns. We block *all*
369 	 * signals during pollts(2).
370 	 */
371 	ATF_REQUIRE_EQ_MSG(ret = pollts(&pfd, 1, &timeout, &mask), 1,
372 	    "got: %d", ret);
373 
374 	/* Check that signals are now longer blocked. */
375 	ATF_REQUIRE_EQ(sigprocmask(SIG_SETMASK, NULL, &mask), 0);
376 	ATF_REQUIRE_EQ_MSG(sigismember(&mask, SIGUSR1), 0,
377 	    "signal mask was changed.");
378 
379 	ATF_REQUIRE_EQ(close(fd), 0);
380 }
381 #endif
382 
383 ATF_TP_ADD_TCS(tp)
384 {
385 
386 	ATF_TP_ADD_TC(tp, poll_3way);
387 	ATF_TP_ADD_TC(tp, poll_basic);
388 	ATF_TP_ADD_TC(tp, poll_err);
389 #ifndef __FreeBSD__
390 	ATF_TP_ADD_TC(tp, pollts_basic);
391 	ATF_TP_ADD_TC(tp, pollts_err);
392 	ATF_TP_ADD_TC(tp, pollts_sigmask);
393 #endif
394 
395 	return atf_no_error();
396 }
397