xref: /openbsd-src/regress/lib/libc/sys/t_poll.c (revision d5ba501974963ce19b098d6f380cdbe48ee29a8a)
1*d5ba5019Smbuhl /*	$OpenBSD: t_poll.c,v 1.3 2022/05/28 18:39:39 mbuhl Exp $	*/
27496d4e5Sbluhm /*	$NetBSD: t_poll.c,v 1.4 2020/07/17 15:34:16 kamil Exp $	*/
3a545a52cSbluhm 
4a545a52cSbluhm /*-
5a545a52cSbluhm  * Copyright (c) 2011 The NetBSD Foundation, Inc.
6a545a52cSbluhm  * All rights reserved.
7a545a52cSbluhm  *
8a545a52cSbluhm  * This code is derived from software contributed to The NetBSD Foundation
9a545a52cSbluhm  * by Matthias Scheler.
10a545a52cSbluhm  *
11a545a52cSbluhm  * Redistribution and use in source and binary forms, with or without
12a545a52cSbluhm  * modification, are permitted provided that the following conditions
13a545a52cSbluhm  * are met:
14a545a52cSbluhm  * 1. Redistributions of source code must retain the above copyright
15a545a52cSbluhm  *    notice, this list of conditions and the following disclaimer.
16a545a52cSbluhm  * 2. Redistributions in binary form must reproduce the above copyright
17a545a52cSbluhm  *    notice, this list of conditions and the following disclaimer in the
18a545a52cSbluhm  *    documentation and/or other materials provided with the distribution.
19a545a52cSbluhm  *
20a545a52cSbluhm  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21a545a52cSbluhm  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22a545a52cSbluhm  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23a545a52cSbluhm  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24a545a52cSbluhm  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25a545a52cSbluhm  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26a545a52cSbluhm  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27a545a52cSbluhm  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28a545a52cSbluhm  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29a545a52cSbluhm  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30a545a52cSbluhm  * POSSIBILITY OF SUCH DAMAGE.
31a545a52cSbluhm  */
32a545a52cSbluhm 
33a545a52cSbluhm #include "macros.h"
34a545a52cSbluhm 
35a545a52cSbluhm #include <sys/time.h>
36a545a52cSbluhm #include <sys/wait.h>
37a545a52cSbluhm 
38a545a52cSbluhm #include "atf-c.h"
39a545a52cSbluhm #include <errno.h>
40a545a52cSbluhm #include <fcntl.h>
41a545a52cSbluhm #include <paths.h>
42a545a52cSbluhm #include <poll.h>
43a545a52cSbluhm #include <stdio.h>
44a545a52cSbluhm #include <signal.h>
45a545a52cSbluhm #include <unistd.h>
46a545a52cSbluhm 
47a545a52cSbluhm static int desc;
48a545a52cSbluhm 
49a545a52cSbluhm static void
child1(void)50a545a52cSbluhm child1(void)
51a545a52cSbluhm {
52a545a52cSbluhm 	struct pollfd pfd;
53a545a52cSbluhm 
54a545a52cSbluhm 	pfd.fd = desc;
55a545a52cSbluhm 	pfd.events = POLLIN | POLLHUP | POLLOUT;
56a545a52cSbluhm 
57a545a52cSbluhm 	(void)poll(&pfd, 1, 2000);
58a545a52cSbluhm 	(void)printf("child1 exit\n");
59a545a52cSbluhm }
60a545a52cSbluhm 
61a545a52cSbluhm static void
child2(void)62a545a52cSbluhm child2(void)
63a545a52cSbluhm {
64a545a52cSbluhm 	struct pollfd pfd;
65a545a52cSbluhm 
66a545a52cSbluhm 	pfd.fd = desc;
67a545a52cSbluhm 	pfd.events = POLLIN | POLLHUP | POLLOUT;
68a545a52cSbluhm 
69a545a52cSbluhm 	(void)sleep(1);
70a545a52cSbluhm 	(void)poll(&pfd, 1, INFTIM);
71a545a52cSbluhm 	(void)printf("child2 exit\n");
72a545a52cSbluhm }
73a545a52cSbluhm 
74a545a52cSbluhm static void
child3(void)75a545a52cSbluhm child3(void)
76a545a52cSbluhm {
77a545a52cSbluhm 	struct pollfd pfd;
78a545a52cSbluhm 
79a545a52cSbluhm 	(void)sleep(5);
80a545a52cSbluhm 
81a545a52cSbluhm 	pfd.fd = desc;
82a545a52cSbluhm 	pfd.events = POLLIN | POLLHUP | POLLOUT;
83a545a52cSbluhm 
84a545a52cSbluhm 	(void)poll(&pfd, 1, INFTIM);
85a545a52cSbluhm 	(void)printf("child3 exit\n");
86a545a52cSbluhm }
87a545a52cSbluhm 
887496d4e5Sbluhm ATF_TC(3way);
897496d4e5Sbluhm ATF_TC_HEAD(3way, tc)
90a545a52cSbluhm {
91a545a52cSbluhm 	atf_tc_set_md_var(tc, "timeout", "15");
92a545a52cSbluhm 	atf_tc_set_md_var(tc, "descr",
93a545a52cSbluhm 	    "Check for 3-way collision for descriptor. First child comes "
94a545a52cSbluhm 	    "and polls on descriptor, second child comes and polls, first "
95a545a52cSbluhm 	    "child times out and exits, third child comes and polls. When "
96a545a52cSbluhm 	    "the wakeup event happens, the two remaining children should "
97a545a52cSbluhm 	    "both be awaken. (kern/17517)");
98a545a52cSbluhm }
99a545a52cSbluhm 
1007496d4e5Sbluhm ATF_TC_BODY(3way, tc)
101a545a52cSbluhm {
102a545a52cSbluhm 	int pf[2];
103a545a52cSbluhm 	int status, i;
104a545a52cSbluhm 	pid_t pid;
105a545a52cSbluhm 
106a545a52cSbluhm 	pipe(pf);
107a545a52cSbluhm 	desc = pf[0];
108a545a52cSbluhm 
109a545a52cSbluhm 	pid = fork();
110a545a52cSbluhm 	ATF_REQUIRE(pid >= 0);
111a545a52cSbluhm 
112a545a52cSbluhm 	if (pid == 0) {
113a545a52cSbluhm 		(void)close(pf[1]);
114a545a52cSbluhm 		child1();
115a545a52cSbluhm 		_exit(0);
116a545a52cSbluhm 		/* NOTREACHED */
117a545a52cSbluhm 	}
118a545a52cSbluhm 
119a545a52cSbluhm 	pid = fork();
120a545a52cSbluhm 	ATF_REQUIRE(pid >= 0);
121a545a52cSbluhm 
122a545a52cSbluhm 	if (pid == 0) {
123a545a52cSbluhm 		(void)close(pf[1]);
124a545a52cSbluhm 		child2();
125a545a52cSbluhm 		_exit(0);
126a545a52cSbluhm 		/* NOTREACHED */
127a545a52cSbluhm 	}
128a545a52cSbluhm 
129a545a52cSbluhm 	pid = fork();
130a545a52cSbluhm 	ATF_REQUIRE( pid >= 0);
131a545a52cSbluhm 
132a545a52cSbluhm 	if (pid == 0) {
133a545a52cSbluhm 		(void)close(pf[1]);
134a545a52cSbluhm 		child3();
135a545a52cSbluhm 		_exit(0);
136a545a52cSbluhm 		/* NOTREACHED */
137a545a52cSbluhm 	}
138a545a52cSbluhm 
139a545a52cSbluhm 	(void)sleep(10);
140a545a52cSbluhm 
141a545a52cSbluhm 	(void)printf("parent write\n");
142a545a52cSbluhm 
143a545a52cSbluhm 	ATF_REQUIRE(write(pf[1], "konec\n", 6) == 6);
144a545a52cSbluhm 
145a545a52cSbluhm 	for(i = 0; i < 3; ++i)
146a545a52cSbluhm 		(void)wait(&status);
147a545a52cSbluhm 
148a545a52cSbluhm 	(void)printf("parent terminated\n");
149a545a52cSbluhm }
150a545a52cSbluhm 
1517496d4e5Sbluhm ATF_TC(basic);
ATF_TC_HEAD(basic,tc)1527496d4e5Sbluhm ATF_TC_HEAD(basic, tc)
153a545a52cSbluhm {
154a545a52cSbluhm 	atf_tc_set_md_var(tc, "timeout", "10");
155a545a52cSbluhm 	atf_tc_set_md_var(tc, "descr",
156a545a52cSbluhm 	    "Basis functionality test for poll(2)");
157a545a52cSbluhm }
158a545a52cSbluhm 
ATF_TC_BODY(basic,tc)1597496d4e5Sbluhm ATF_TC_BODY(basic, tc)
160a545a52cSbluhm {
161a545a52cSbluhm 	int fds[2];
162a545a52cSbluhm 	struct pollfd pfds[2];
163a545a52cSbluhm 	int ret;
164a545a52cSbluhm 
165a545a52cSbluhm 	ATF_REQUIRE_EQ(pipe(fds), 0);
166a545a52cSbluhm 
167a545a52cSbluhm 	pfds[0].fd = fds[0];
168a545a52cSbluhm 	pfds[0].events = POLLIN;
169a545a52cSbluhm 	pfds[1].fd = fds[1];
170a545a52cSbluhm 	pfds[1].events = POLLOUT;
171a545a52cSbluhm 
172a545a52cSbluhm 	/*
173a545a52cSbluhm 	 * Check that we get a timeout waiting for data on the read end
174a545a52cSbluhm 	 * of our pipe.
175a545a52cSbluhm 	 */
176a545a52cSbluhm 	pfds[0].revents = -1;
177a545a52cSbluhm 	pfds[1].revents = -1;
178*d5ba5019Smbuhl 	ret = poll(&pfds[0], 1, 1);
179*d5ba5019Smbuhl 	ATF_REQUIRE_EQ_MSG(ret, 0, "got: %d", ret);
180a545a52cSbluhm 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
181a545a52cSbluhm 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, -1, "got: %d", pfds[1].revents);
182a545a52cSbluhm 
183a545a52cSbluhm 	/* Check that the write end of the pipe as reported as ready. */
184a545a52cSbluhm 	pfds[0].revents = -1;
185a545a52cSbluhm 	pfds[1].revents = -1;
186*d5ba5019Smbuhl 	ret = poll(&pfds[1], 1, 1);
187*d5ba5019Smbuhl 	ATF_REQUIRE_EQ_MSG(ret, 1, "got: %d", ret);
188a545a52cSbluhm 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, -1, "got: %d", pfds[0].revents);
189a545a52cSbluhm 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",\
190a545a52cSbluhm 	    pfds[1].revents);
191a545a52cSbluhm 
192a545a52cSbluhm 	/* Check that only the write end of the pipe as reported as ready. */
193a545a52cSbluhm 	pfds[0].revents = -1;
194a545a52cSbluhm 	pfds[1].revents = -1;
195*d5ba5019Smbuhl 	ret = poll(pfds, 2, 1);
196*d5ba5019Smbuhl 	ATF_REQUIRE_EQ_MSG(ret, 1, "got: %d", ret);
197a545a52cSbluhm 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
198a545a52cSbluhm 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
199a545a52cSbluhm 	    pfds[1].revents);
200a545a52cSbluhm 
201a545a52cSbluhm 	/* Write data to our pipe. */
202a545a52cSbluhm 	ATF_REQUIRE_EQ(write(fds[1], "", 1), 1);
203a545a52cSbluhm 
204a545a52cSbluhm 	/* Check that both ends of our pipe are reported as ready. */
205a545a52cSbluhm 	pfds[0].revents = -1;
206a545a52cSbluhm 	pfds[1].revents = -1;
207*d5ba5019Smbuhl 	ret = poll(pfds, 2, 1);
208*d5ba5019Smbuhl 	ATF_REQUIRE_EQ_MSG(ret, 2, "got: %d", ret);
209a545a52cSbluhm 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, POLLIN, "got: %d",
210a545a52cSbluhm 	    pfds[0].revents);
211a545a52cSbluhm 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
212a545a52cSbluhm 	    pfds[1].revents);
213a545a52cSbluhm 
214a545a52cSbluhm 	ATF_REQUIRE_EQ(close(fds[0]), 0);
215a545a52cSbluhm 	ATF_REQUIRE_EQ(close(fds[1]), 0);
216a545a52cSbluhm }
217a545a52cSbluhm 
2187496d4e5Sbluhm ATF_TC(err);
ATF_TC_HEAD(err,tc)2197496d4e5Sbluhm ATF_TC_HEAD(err, tc)
220a545a52cSbluhm {
221a545a52cSbluhm 	atf_tc_set_md_var(tc, "descr", "Check errors from poll(2)");
222a545a52cSbluhm }
223a545a52cSbluhm 
ATF_TC_BODY(err,tc)2247496d4e5Sbluhm ATF_TC_BODY(err, tc)
225a545a52cSbluhm {
226a545a52cSbluhm 	struct pollfd pfd;
227a545a52cSbluhm 	int fd = 0;
228a545a52cSbluhm 
229a545a52cSbluhm 	pfd.fd = fd;
230a545a52cSbluhm 	pfd.events = POLLIN;
231a545a52cSbluhm 
232a545a52cSbluhm 	errno = 0;
233a545a52cSbluhm 	ATF_REQUIRE_ERRNO(EFAULT, poll((struct pollfd *)-1, 1, -1) == -1);
234a545a52cSbluhm 
235a545a52cSbluhm 	errno = 0;
236a545a52cSbluhm 	ATF_REQUIRE_ERRNO(EINVAL, poll(&pfd, 1, -2) == -1);
237a545a52cSbluhm }
238a545a52cSbluhm 
ATF_TP_ADD_TCS(tp)239a545a52cSbluhm ATF_TP_ADD_TCS(tp)
240a545a52cSbluhm {
241a545a52cSbluhm 
2427496d4e5Sbluhm 	ATF_TP_ADD_TC(tp, 3way);
2437496d4e5Sbluhm 	ATF_TP_ADD_TC(tp, basic);
2447496d4e5Sbluhm 	ATF_TP_ADD_TC(tp, err);
245a545a52cSbluhm 
246a545a52cSbluhm 	return atf_no_error();
247a545a52cSbluhm }
248