xref: /freebsd/contrib/netbsd-tests/lib/libc/sys/t_poll.c (revision 6186fd1857626de0f7cb1a9e4dff19082f9ebb11)
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 ATF_TC(pollts_basic);
237 ATF_TC_HEAD(pollts_basic, tc)
238 {
239 	atf_tc_set_md_var(tc, "timeout", "10");
240 	atf_tc_set_md_var(tc, "descr",
241 	    "Basis functionality test for pollts(2)");
242 }
243 
244 ATF_TC_BODY(pollts_basic, tc)
245 {
246 	int fds[2];
247 	struct pollfd pfds[2];
248 	struct timespec timeout;
249 	int ret;
250 
251 	ATF_REQUIRE_EQ(pipe(fds), 0);
252 
253 	pfds[0].fd = fds[0];
254 	pfds[0].events = POLLIN;
255 	pfds[1].fd = fds[1];
256 	pfds[1].events = POLLOUT;
257 
258 	/* Use a timeout of 1 second. */
259 	timeout.tv_sec = 1;
260 	timeout.tv_nsec = 0;
261 
262 	/*
263 	 * Check that we get a timeout waiting for data on the read end
264 	 * of our pipe.
265 	 */
266 	pfds[0].revents = -1;
267 	pfds[1].revents = -1;
268 	ATF_REQUIRE_EQ_MSG(ret = pollts(&pfds[0], 1, &timeout, NULL), 0,
269 	    "got: %d", ret);
270 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
271 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, -1, "got: %d", pfds[1].revents);
272 
273 	/* Check that the write end of the pipe as reported as ready. */
274 	pfds[0].revents = -1;
275 	pfds[1].revents = -1;
276 	ATF_REQUIRE_EQ_MSG(ret = pollts(&pfds[1], 1, &timeout, NULL), 1,
277 	    "got: %d", ret);
278 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, -1, "got: %d", pfds[0].revents);
279 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",\
280 	    pfds[1].revents);
281 
282 	/* Check that only the write end of the pipe as reported as ready. */
283 	pfds[0].revents = -1;
284 	pfds[1].revents = -1;
285 	ATF_REQUIRE_EQ_MSG(ret = pollts(pfds, 2, &timeout, NULL), 1,
286 	    "got: %d", ret);
287 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
288 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
289 	    pfds[1].revents);
290 
291 	/* Write data to our pipe. */
292 	ATF_REQUIRE_EQ(write(fds[1], "", 1), 1);
293 
294 	/* Check that both ends of our pipe are reported as ready. */
295 	pfds[0].revents = -1;
296 	pfds[1].revents = -1;
297 	ATF_REQUIRE_EQ_MSG(ret = pollts(pfds, 2, &timeout, NULL), 2,
298 	    "got: %d", ret);
299 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, POLLIN, "got: %d",
300 	    pfds[0].revents);
301 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
302 	    pfds[1].revents);
303 
304 	ATF_REQUIRE_EQ(close(fds[0]), 0);
305 	ATF_REQUIRE_EQ(close(fds[1]), 0);
306 }
307 
308 ATF_TC(pollts_err);
309 ATF_TC_HEAD(pollts_err, tc)
310 {
311 	atf_tc_set_md_var(tc, "descr", "Check errors from pollts(2)");
312 }
313 
314 ATF_TC_BODY(pollts_err, tc)
315 {
316 	struct timespec timeout;
317 	struct pollfd pfd;
318 	int fd = 0;
319 
320 	pfd.fd = fd;
321 	pfd.events = POLLIN;
322 
323 	timeout.tv_sec = 1;
324 	timeout.tv_nsec = 0;
325 
326 	errno = 0;
327 	ATF_REQUIRE_ERRNO(EFAULT, pollts((void *)-1, 1, &timeout, NULL) == -1);
328 
329 	timeout.tv_sec = -1;
330 	timeout.tv_nsec = -1;
331 
332 	errno = 0;
333 	ATF_REQUIRE_ERRNO(EINVAL, pollts(&pfd, 1, &timeout, NULL) == -1);
334 }
335 
336 ATF_TC(pollts_sigmask);
337 ATF_TC_HEAD(pollts_sigmask, tc)
338 {
339 	atf_tc_set_md_var(tc, "timeout", "10");
340 	atf_tc_set_md_var(tc, "descr",
341 	    "Check that pollts(2) restores the signal mask (PR kern/44986)");
342 }
343 
344 ATF_TC_BODY(pollts_sigmask, tc)
345 {
346 	int fd;
347 	struct pollfd pfd;
348 	struct timespec timeout;
349 	sigset_t mask;
350 	int ret;
351 
352 	fd = open(_PATH_DEVNULL, O_RDONLY);
353 	ATF_REQUIRE(fd >= 0);
354 
355 	pfd.fd = fd;
356 	pfd.events = POLLIN;
357 
358 	/* Use a timeout of 1 second. */
359 	timeout.tv_sec = 1;
360 	timeout.tv_nsec = 0;
361 
362 	/* Unblock all signals. */
363 	ATF_REQUIRE_EQ(sigfillset(&mask), 0);
364 	ATF_REQUIRE_EQ(sigprocmask(SIG_UNBLOCK, &mask, NULL), 0);
365 
366 	/*
367 	 * Check that pollts(2) immediately returns. We block *all*
368 	 * signals during pollts(2).
369 	 */
370 	ATF_REQUIRE_EQ_MSG(ret = pollts(&pfd, 1, &timeout, &mask), 1,
371 	    "got: %d", ret);
372 
373 	/* Check that signals are now longer blocked. */
374 	ATF_REQUIRE_EQ(sigprocmask(SIG_SETMASK, NULL, &mask), 0);
375 	ATF_REQUIRE_EQ_MSG(sigismember(&mask, SIGUSR1), 0,
376 	    "signal mask was changed.");
377 
378 	ATF_REQUIRE_EQ(close(fd), 0);
379 }
380 
381 ATF_TP_ADD_TCS(tp)
382 {
383 
384 	ATF_TP_ADD_TC(tp, poll_3way);
385 	ATF_TP_ADD_TC(tp, poll_basic);
386 	ATF_TP_ADD_TC(tp, poll_err);
387 	ATF_TP_ADD_TC(tp, pollts_basic);
388 	ATF_TP_ADD_TC(tp, pollts_err);
389 	ATF_TP_ADD_TC(tp, pollts_sigmask);
390 
391 	return atf_no_error();
392 }
393