xref: /netbsd-src/tests/lib/libc/sys/t_poll.c (revision 5de7d31bd2441784bc14a9fce6877163bff6f1e2)
1*5de7d31bSthorpej /*	$NetBSD: t_poll.c,v 1.8 2021/10/02 17:32:55 thorpej Exp $	*/
2068fb4f1Sjruoho 
3068fb4f1Sjruoho /*-
4068fb4f1Sjruoho  * Copyright (c) 2011 The NetBSD Foundation, Inc.
5068fb4f1Sjruoho  * All rights reserved.
6068fb4f1Sjruoho  *
7068fb4f1Sjruoho  * This code is derived from software contributed to The NetBSD Foundation
8068fb4f1Sjruoho  * by Matthias Scheler.
9068fb4f1Sjruoho  *
10068fb4f1Sjruoho  * Redistribution and use in source and binary forms, with or without
11068fb4f1Sjruoho  * modification, are permitted provided that the following conditions
12068fb4f1Sjruoho  * are met:
13068fb4f1Sjruoho  * 1. Redistributions of source code must retain the above copyright
14068fb4f1Sjruoho  *    notice, this list of conditions and the following disclaimer.
15068fb4f1Sjruoho  * 2. Redistributions in binary form must reproduce the above copyright
16068fb4f1Sjruoho  *    notice, this list of conditions and the following disclaimer in the
17068fb4f1Sjruoho  *    documentation and/or other materials provided with the distribution.
18068fb4f1Sjruoho  *
19068fb4f1Sjruoho  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20068fb4f1Sjruoho  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21068fb4f1Sjruoho  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22068fb4f1Sjruoho  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23068fb4f1Sjruoho  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24068fb4f1Sjruoho  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25068fb4f1Sjruoho  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26068fb4f1Sjruoho  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27068fb4f1Sjruoho  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28068fb4f1Sjruoho  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29068fb4f1Sjruoho  * POSSIBILITY OF SUCH DAMAGE.
30068fb4f1Sjruoho  */
31068fb4f1Sjruoho 
326dff442fSthorpej #include <sys/stat.h>
33068fb4f1Sjruoho #include <sys/time.h>
34175ae785Sjruoho #include <sys/wait.h>
35068fb4f1Sjruoho 
36068fb4f1Sjruoho #include <atf-c.h>
37068fb4f1Sjruoho #include <errno.h>
38068fb4f1Sjruoho #include <fcntl.h>
39068fb4f1Sjruoho #include <paths.h>
40068fb4f1Sjruoho #include <poll.h>
41175ae785Sjruoho #include <stdio.h>
42bad2e9f9Sthorpej #include <stdlib.h>
43068fb4f1Sjruoho #include <signal.h>
44068fb4f1Sjruoho #include <unistd.h>
45068fb4f1Sjruoho 
46175ae785Sjruoho static int desc;
47175ae785Sjruoho 
48175ae785Sjruoho static void
child1(void)49175ae785Sjruoho child1(void)
50175ae785Sjruoho {
51175ae785Sjruoho 	struct pollfd pfd;
52175ae785Sjruoho 
53175ae785Sjruoho 	pfd.fd = desc;
54175ae785Sjruoho 	pfd.events = POLLIN | POLLHUP | POLLOUT;
55175ae785Sjruoho 
56175ae785Sjruoho 	(void)poll(&pfd, 1, 2000);
57175ae785Sjruoho 	(void)printf("child1 exit\n");
58175ae785Sjruoho }
59175ae785Sjruoho 
60175ae785Sjruoho static void
child2(void)61175ae785Sjruoho child2(void)
62175ae785Sjruoho {
63175ae785Sjruoho 	struct pollfd pfd;
64175ae785Sjruoho 
65175ae785Sjruoho 	pfd.fd = desc;
66175ae785Sjruoho 	pfd.events = POLLIN | POLLHUP | POLLOUT;
67175ae785Sjruoho 
68175ae785Sjruoho 	(void)sleep(1);
69175ae785Sjruoho 	(void)poll(&pfd, 1, INFTIM);
70175ae785Sjruoho 	(void)printf("child2 exit\n");
71175ae785Sjruoho }
72175ae785Sjruoho 
73175ae785Sjruoho static void
child3(void)74175ae785Sjruoho child3(void)
75175ae785Sjruoho {
76175ae785Sjruoho 	struct pollfd pfd;
77175ae785Sjruoho 
78175ae785Sjruoho 	(void)sleep(5);
79175ae785Sjruoho 
80175ae785Sjruoho 	pfd.fd = desc;
81175ae785Sjruoho 	pfd.events = POLLIN | POLLHUP | POLLOUT;
82175ae785Sjruoho 
83175ae785Sjruoho 	(void)poll(&pfd, 1, INFTIM);
84175ae785Sjruoho 	(void)printf("child3 exit\n");
85175ae785Sjruoho }
86175ae785Sjruoho 
8707e8492eSkamil ATF_TC(3way);
8807e8492eSkamil ATF_TC_HEAD(3way, tc)
89175ae785Sjruoho {
90175ae785Sjruoho 	atf_tc_set_md_var(tc, "timeout", "15");
91175ae785Sjruoho 	atf_tc_set_md_var(tc, "descr",
92175ae785Sjruoho 	    "Check for 3-way collision for descriptor. First child comes "
93175ae785Sjruoho 	    "and polls on descriptor, second child comes and polls, first "
94175ae785Sjruoho 	    "child times out and exits, third child comes and polls. When "
95175ae785Sjruoho 	    "the wakeup event happens, the two remaining children should "
96175ae785Sjruoho 	    "both be awaken. (kern/17517)");
97175ae785Sjruoho }
98175ae785Sjruoho 
9907e8492eSkamil ATF_TC_BODY(3way, tc)
100175ae785Sjruoho {
101175ae785Sjruoho 	int pf[2];
102175ae785Sjruoho 	int status, i;
103175ae785Sjruoho 	pid_t pid;
104175ae785Sjruoho 
105175ae785Sjruoho 	pipe(pf);
106175ae785Sjruoho 	desc = pf[0];
107175ae785Sjruoho 
108175ae785Sjruoho 	pid = fork();
109175ae785Sjruoho 	ATF_REQUIRE(pid >= 0);
110175ae785Sjruoho 
111175ae785Sjruoho 	if (pid == 0) {
112175ae785Sjruoho 		(void)close(pf[1]);
113175ae785Sjruoho 		child1();
114175ae785Sjruoho 		_exit(0);
115175ae785Sjruoho 		/* NOTREACHED */
116175ae785Sjruoho 	}
117175ae785Sjruoho 
118175ae785Sjruoho 	pid = fork();
119175ae785Sjruoho 	ATF_REQUIRE(pid >= 0);
120175ae785Sjruoho 
121175ae785Sjruoho 	if (pid == 0) {
122175ae785Sjruoho 		(void)close(pf[1]);
123175ae785Sjruoho 		child2();
124175ae785Sjruoho 		_exit(0);
125175ae785Sjruoho 		/* NOTREACHED */
126175ae785Sjruoho 	}
127175ae785Sjruoho 
128175ae785Sjruoho 	pid = fork();
129175ae785Sjruoho 	ATF_REQUIRE( pid >= 0);
130175ae785Sjruoho 
131175ae785Sjruoho 	if (pid == 0) {
132175ae785Sjruoho 		(void)close(pf[1]);
133175ae785Sjruoho 		child3();
134175ae785Sjruoho 		_exit(0);
135175ae785Sjruoho 		/* NOTREACHED */
136175ae785Sjruoho 	}
137175ae785Sjruoho 
138175ae785Sjruoho 	(void)sleep(10);
139175ae785Sjruoho 
140175ae785Sjruoho 	(void)printf("parent write\n");
141175ae785Sjruoho 
142175ae785Sjruoho 	ATF_REQUIRE(write(pf[1], "konec\n", 6) == 6);
143175ae785Sjruoho 
144175ae785Sjruoho 	for(i = 0; i < 3; ++i)
145175ae785Sjruoho 		(void)wait(&status);
146175ae785Sjruoho 
147175ae785Sjruoho 	(void)printf("parent terminated\n");
148175ae785Sjruoho }
149175ae785Sjruoho 
15007e8492eSkamil ATF_TC(basic);
ATF_TC_HEAD(basic,tc)15107e8492eSkamil ATF_TC_HEAD(basic, tc)
152068fb4f1Sjruoho {
153068fb4f1Sjruoho 	atf_tc_set_md_var(tc, "timeout", "10");
154068fb4f1Sjruoho 	atf_tc_set_md_var(tc, "descr",
155068fb4f1Sjruoho 	    "Basis functionality test for poll(2)");
156068fb4f1Sjruoho }
157068fb4f1Sjruoho 
ATF_TC_BODY(basic,tc)15807e8492eSkamil ATF_TC_BODY(basic, tc)
159068fb4f1Sjruoho {
160068fb4f1Sjruoho 	int fds[2];
161068fb4f1Sjruoho 	struct pollfd pfds[2];
162068fb4f1Sjruoho 	int ret;
163068fb4f1Sjruoho 
164068fb4f1Sjruoho 	ATF_REQUIRE_EQ(pipe(fds), 0);
165068fb4f1Sjruoho 
166068fb4f1Sjruoho 	pfds[0].fd = fds[0];
167068fb4f1Sjruoho 	pfds[0].events = POLLIN;
168068fb4f1Sjruoho 	pfds[1].fd = fds[1];
169068fb4f1Sjruoho 	pfds[1].events = POLLOUT;
170068fb4f1Sjruoho 
171068fb4f1Sjruoho 	/*
172068fb4f1Sjruoho 	 * Check that we get a timeout waiting for data on the read end
173068fb4f1Sjruoho 	 * of our pipe.
174068fb4f1Sjruoho 	 */
175068fb4f1Sjruoho 	pfds[0].revents = -1;
176068fb4f1Sjruoho 	pfds[1].revents = -1;
177068fb4f1Sjruoho 	ATF_REQUIRE_EQ_MSG(ret = poll(&pfds[0], 1, 1), 0,
178068fb4f1Sjruoho 	    "got: %d", ret);
179068fb4f1Sjruoho 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
180068fb4f1Sjruoho 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, -1, "got: %d", pfds[1].revents);
181068fb4f1Sjruoho 
182068fb4f1Sjruoho 	/* Check that the write end of the pipe as reported as ready. */
183068fb4f1Sjruoho 	pfds[0].revents = -1;
184068fb4f1Sjruoho 	pfds[1].revents = -1;
185068fb4f1Sjruoho 	ATF_REQUIRE_EQ_MSG(ret = poll(&pfds[1], 1, 1), 1,
186068fb4f1Sjruoho 	    "got: %d", ret);
187068fb4f1Sjruoho 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, -1, "got: %d", pfds[0].revents);
188068fb4f1Sjruoho 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",\
189068fb4f1Sjruoho 	    pfds[1].revents);
190068fb4f1Sjruoho 
191068fb4f1Sjruoho 	/* Check that only the write end of the pipe as reported as ready. */
192068fb4f1Sjruoho 	pfds[0].revents = -1;
193068fb4f1Sjruoho 	pfds[1].revents = -1;
194068fb4f1Sjruoho 	ATF_REQUIRE_EQ_MSG(ret = poll(pfds, 2, 1), 1,
195068fb4f1Sjruoho 	    "got: %d", ret);
196068fb4f1Sjruoho 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
197068fb4f1Sjruoho 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
198068fb4f1Sjruoho 	    pfds[1].revents);
199068fb4f1Sjruoho 
200068fb4f1Sjruoho 	/* Write data to our pipe. */
201068fb4f1Sjruoho 	ATF_REQUIRE_EQ(write(fds[1], "", 1), 1);
202068fb4f1Sjruoho 
203068fb4f1Sjruoho 	/* Check that both ends of our pipe are reported as ready. */
204068fb4f1Sjruoho 	pfds[0].revents = -1;
205068fb4f1Sjruoho 	pfds[1].revents = -1;
206068fb4f1Sjruoho 	ATF_REQUIRE_EQ_MSG(ret = poll(pfds, 2, 1), 2,
207068fb4f1Sjruoho 	    "got: %d", ret);
208068fb4f1Sjruoho 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, POLLIN, "got: %d",
209068fb4f1Sjruoho 	    pfds[0].revents);
210068fb4f1Sjruoho 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
211068fb4f1Sjruoho 	    pfds[1].revents);
212068fb4f1Sjruoho 
213068fb4f1Sjruoho 	ATF_REQUIRE_EQ(close(fds[0]), 0);
214068fb4f1Sjruoho 	ATF_REQUIRE_EQ(close(fds[1]), 0);
215068fb4f1Sjruoho }
216068fb4f1Sjruoho 
21707e8492eSkamil ATF_TC(err);
ATF_TC_HEAD(err,tc)21807e8492eSkamil ATF_TC_HEAD(err, tc)
219068fb4f1Sjruoho {
220068fb4f1Sjruoho 	atf_tc_set_md_var(tc, "descr", "Check errors from poll(2)");
221068fb4f1Sjruoho }
222068fb4f1Sjruoho 
ATF_TC_BODY(err,tc)22307e8492eSkamil ATF_TC_BODY(err, tc)
224068fb4f1Sjruoho {
225068fb4f1Sjruoho 	struct pollfd pfd;
226068fb4f1Sjruoho 	int fd = 0;
227068fb4f1Sjruoho 
228068fb4f1Sjruoho 	pfd.fd = fd;
229068fb4f1Sjruoho 	pfd.events = POLLIN;
230068fb4f1Sjruoho 
231068fb4f1Sjruoho 	errno = 0;
232068fb4f1Sjruoho 	ATF_REQUIRE_ERRNO(EFAULT, poll((struct pollfd *)-1, 1, -1) == -1);
233068fb4f1Sjruoho 
234068fb4f1Sjruoho 	errno = 0;
235068fb4f1Sjruoho 	ATF_REQUIRE_ERRNO(EINVAL, poll(&pfd, 1, -2) == -1);
236068fb4f1Sjruoho }
237068fb4f1Sjruoho 
2386dff442fSthorpej static const char	fifo_path[] = "pollhup_fifo";
2396dff442fSthorpej 
2406dff442fSthorpej static void
fifo_support(void)2416dff442fSthorpej fifo_support(void)
2426dff442fSthorpej {
2436dff442fSthorpej 	errno = 0;
2446dff442fSthorpej 	if (mkfifo(fifo_path, 0600) == 0) {
2456dff442fSthorpej 		ATF_REQUIRE(unlink(fifo_path) == 0);
2466dff442fSthorpej 		return;
2476dff442fSthorpej 	}
2486dff442fSthorpej 
2496dff442fSthorpej 	if (errno == EOPNOTSUPP) {
2506dff442fSthorpej 		atf_tc_skip("the kernel does not support FIFOs");
2516dff442fSthorpej 	} else {
2526dff442fSthorpej 		atf_tc_fail("mkfifo(2) failed");
2536dff442fSthorpej 	}
2546dff442fSthorpej }
2556dff442fSthorpej 
256bad2e9f9Sthorpej ATF_TC_WITH_CLEANUP(fifo_inout);
ATF_TC_HEAD(fifo_inout,tc)257bad2e9f9Sthorpej ATF_TC_HEAD(fifo_inout, tc)
258bad2e9f9Sthorpej {
259bad2e9f9Sthorpej 	atf_tc_set_md_var(tc, "descr",
260bad2e9f9Sthorpej 	    "Check POLLIN/POLLOUT behavior with fifos");
261bad2e9f9Sthorpej }
262bad2e9f9Sthorpej 
ATF_TC_BODY(fifo_inout,tc)263bad2e9f9Sthorpej ATF_TC_BODY(fifo_inout, tc)
264bad2e9f9Sthorpej {
265bad2e9f9Sthorpej 	struct pollfd pfd[2];
266bad2e9f9Sthorpej 	char *buf;
267bad2e9f9Sthorpej 	int rfd, wfd;
268bad2e9f9Sthorpej 	long pipe_buf;
269bad2e9f9Sthorpej 
270bad2e9f9Sthorpej 	fifo_support();
271bad2e9f9Sthorpej 
272bad2e9f9Sthorpej 	ATF_REQUIRE(mkfifo(fifo_path, 0600) == 0);
273bad2e9f9Sthorpej 	ATF_REQUIRE((rfd = open(fifo_path, O_RDONLY | O_NONBLOCK)) >= 0);
274bad2e9f9Sthorpej 	ATF_REQUIRE((wfd = open(fifo_path, O_WRONLY | O_NONBLOCK)) >= 0);
275bad2e9f9Sthorpej 
276bad2e9f9Sthorpej 	/* Get the maximum atomic pipe write size. */
277bad2e9f9Sthorpej 	pipe_buf = fpathconf(wfd, _PC_PIPE_BUF);
278bad2e9f9Sthorpej 	ATF_REQUIRE(pipe_buf > 1);
279bad2e9f9Sthorpej 
280bad2e9f9Sthorpej 	buf = malloc(pipe_buf);
281bad2e9f9Sthorpej 	ATF_REQUIRE(buf != NULL);
282bad2e9f9Sthorpej 
283bad2e9f9Sthorpej 	memset(&pfd, 0, sizeof(pfd));
284bad2e9f9Sthorpej 	pfd[0].fd = rfd;
285bad2e9f9Sthorpej 	pfd[0].events = POLLIN | POLLRDNORM;
286bad2e9f9Sthorpej 	pfd[1].fd = wfd;
287bad2e9f9Sthorpej 	pfd[1].events = POLLOUT | POLLWRNORM;
288bad2e9f9Sthorpej 
289bad2e9f9Sthorpej 	/* We expect the FIFO to be writable but not readable. */
290bad2e9f9Sthorpej 	ATF_REQUIRE(poll(pfd, 2, 0) == 1);
291bad2e9f9Sthorpej 	ATF_REQUIRE(pfd[0].revents == 0);
292bad2e9f9Sthorpej 	ATF_REQUIRE(pfd[1].revents == (POLLOUT | POLLWRNORM));
293bad2e9f9Sthorpej 
294bad2e9f9Sthorpej 	/* Write a single byte of data into the FIFO. */
295bad2e9f9Sthorpej 	ATF_REQUIRE(write(wfd, buf, 1) == 1);
296bad2e9f9Sthorpej 
297bad2e9f9Sthorpej 	/* We expect the FIFO to be readable and writable. */
298bad2e9f9Sthorpej 	ATF_REQUIRE(poll(pfd, 2, 0) == 2);
299bad2e9f9Sthorpej 	ATF_REQUIRE(pfd[0].revents == (POLLIN | POLLRDNORM));
300bad2e9f9Sthorpej 	ATF_REQUIRE(pfd[1].revents == (POLLOUT | POLLWRNORM));
301bad2e9f9Sthorpej 
302bad2e9f9Sthorpej 	/* Read that single byte back out. */
303bad2e9f9Sthorpej 	ATF_REQUIRE(read(rfd, buf, 1) == 1);
304bad2e9f9Sthorpej 
305bad2e9f9Sthorpej 	/*
306bad2e9f9Sthorpej 	 * Write data into the FIFO until it is full, which is
307bad2e9f9Sthorpej 	 * defined as insufficient buffer space to hold a the
308bad2e9f9Sthorpej 	 * maximum atomic pipe write size.
309bad2e9f9Sthorpej 	 */
310bad2e9f9Sthorpej 	while (write(wfd, buf, pipe_buf) != -1) {
311bad2e9f9Sthorpej 		continue;
312bad2e9f9Sthorpej 	}
313bad2e9f9Sthorpej 	ATF_REQUIRE(errno == EAGAIN);
314bad2e9f9Sthorpej 
315bad2e9f9Sthorpej 	/* We expect the FIFO to be readble but not writable. */
316bad2e9f9Sthorpej 	ATF_REQUIRE(poll(pfd, 2, 0) == 1);
317bad2e9f9Sthorpej 	ATF_REQUIRE(pfd[0].revents == (POLLIN | POLLRDNORM));
318bad2e9f9Sthorpej 	ATF_REQUIRE(pfd[1].revents == 0);
319bad2e9f9Sthorpej 
320bad2e9f9Sthorpej 	/* Read a single byte of data from the FIFO. */
321bad2e9f9Sthorpej 	ATF_REQUIRE(read(rfd, buf, 1) == 1);
322bad2e9f9Sthorpej 
323bad2e9f9Sthorpej 	/*
324bad2e9f9Sthorpej 	 * Because we have read only a single byte out, there will
325bad2e9f9Sthorpej 	 * be insufficient space for a pipe_buf-sized message, so
326bad2e9f9Sthorpej 	 * the FIFO should still not be writable.
327bad2e9f9Sthorpej 	 */
328bad2e9f9Sthorpej 	ATF_REQUIRE(poll(pfd, 2, 0) == 1);
329bad2e9f9Sthorpej 	ATF_REQUIRE(pfd[0].revents == (POLLIN | POLLRDNORM));
330bad2e9f9Sthorpej 	ATF_REQUIRE(pfd[1].revents == 0);
331bad2e9f9Sthorpej 
332bad2e9f9Sthorpej 	/*
333*5de7d31bSthorpej 	 * Now read enough so that exactly pipe_buf space should
334*5de7d31bSthorpej 	 * be available.  The FIFO should be writable after that.
335*5de7d31bSthorpej 	 * N.B. we don't care if it's readable at this point.
336*5de7d31bSthorpej 	 */
337*5de7d31bSthorpej 	ATF_REQUIRE(read(rfd, buf, pipe_buf - 1) == pipe_buf - 1);
338*5de7d31bSthorpej 	ATF_REQUIRE(poll(pfd, 2, 0) >= 1);
339*5de7d31bSthorpej 	ATF_REQUIRE(pfd[1].revents == (POLLOUT | POLLWRNORM));
340*5de7d31bSthorpej 
341*5de7d31bSthorpej 	/*
342bad2e9f9Sthorpej 	 * Now read all of the data out of the FIFO and ensure that
343bad2e9f9Sthorpej 	 * we get back to the initial state.
344bad2e9f9Sthorpej 	 */
345bad2e9f9Sthorpej 	while (read(rfd, buf, pipe_buf) != -1) {
346bad2e9f9Sthorpej 		continue;
347bad2e9f9Sthorpej 	}
348bad2e9f9Sthorpej 	ATF_REQUIRE(errno == EAGAIN);
349bad2e9f9Sthorpej 
350bad2e9f9Sthorpej 	ATF_REQUIRE(poll(pfd, 2, 0) == 1);
351bad2e9f9Sthorpej 	ATF_REQUIRE(pfd[0].revents == 0);
352bad2e9f9Sthorpej 	ATF_REQUIRE(pfd[1].revents == (POLLOUT | POLLWRNORM));
353bad2e9f9Sthorpej 
354bad2e9f9Sthorpej 	(void)close(wfd);
355bad2e9f9Sthorpej 	(void)close(rfd);
356bad2e9f9Sthorpej }
357bad2e9f9Sthorpej 
ATF_TC_CLEANUP(fifo_inout,tc)358bad2e9f9Sthorpej ATF_TC_CLEANUP(fifo_inout, tc)
359bad2e9f9Sthorpej {
360bad2e9f9Sthorpej 	(void)unlink(fifo_path);
361bad2e9f9Sthorpej }
362bad2e9f9Sthorpej 
3636dff442fSthorpej ATF_TC_WITH_CLEANUP(fifo_hup1);
ATF_TC_HEAD(fifo_hup1,tc)3646dff442fSthorpej ATF_TC_HEAD(fifo_hup1, tc)
3656dff442fSthorpej {
3666dff442fSthorpej 	atf_tc_set_md_var(tc, "descr",
3676dff442fSthorpej 	    "Check POLLHUP behavior with fifos [1]");
3686dff442fSthorpej }
3696dff442fSthorpej 
ATF_TC_BODY(fifo_hup1,tc)3706dff442fSthorpej ATF_TC_BODY(fifo_hup1, tc)
3716dff442fSthorpej {
3726dff442fSthorpej 	struct pollfd pfd;
3736dff442fSthorpej 	int rfd, wfd;
3746dff442fSthorpej 
3756dff442fSthorpej 	fifo_support();
3766dff442fSthorpej 
3776dff442fSthorpej 	ATF_REQUIRE(mkfifo(fifo_path, 0600) == 0);
3786dff442fSthorpej 	ATF_REQUIRE((rfd = open(fifo_path, O_RDONLY | O_NONBLOCK)) >= 0);
3796dff442fSthorpej 	ATF_REQUIRE((wfd = open(fifo_path, O_WRONLY)) >= 0);
3806dff442fSthorpej 
3816dff442fSthorpej 	memset(&pfd, 0, sizeof(pfd));
3826dff442fSthorpej 	pfd.fd = rfd;
3836dff442fSthorpej 	pfd.events = POLLIN;
3846dff442fSthorpej 
3856dff442fSthorpej 	(void)close(wfd);
3866dff442fSthorpej 
3876dff442fSthorpej 	ATF_REQUIRE(poll(&pfd, 1, 0) == 1);
3886dff442fSthorpej 	ATF_REQUIRE((pfd.revents & POLLHUP) != 0);
389a0231a42Sthorpej 
390a0231a42Sthorpej 	/*
391a0231a42Sthorpej 	 * Check that POLLHUP is cleared when a writer re-connects.
392a0231a42Sthorpej 	 * Since the writer will not put any data into the FIFO, we
393a0231a42Sthorpej 	 * expect no events.
394a0231a42Sthorpej 	 */
395a0231a42Sthorpej 	memset(&pfd, 0, sizeof(pfd));
396a0231a42Sthorpej 	pfd.fd = rfd;
397a0231a42Sthorpej 	pfd.events = POLLIN;
398a0231a42Sthorpej 
399a0231a42Sthorpej 	ATF_REQUIRE((wfd = open(fifo_path, O_WRONLY)) >= 0);
400a0231a42Sthorpej 	ATF_REQUIRE(poll(&pfd, 1, 0) == 0);
4016dff442fSthorpej }
4026dff442fSthorpej 
ATF_TC_CLEANUP(fifo_hup1,tc)4036dff442fSthorpej ATF_TC_CLEANUP(fifo_hup1, tc)
4046dff442fSthorpej {
4056dff442fSthorpej 	(void)unlink(fifo_path);
4066dff442fSthorpej }
4076dff442fSthorpej 
4086dff442fSthorpej ATF_TC_WITH_CLEANUP(fifo_hup2);
ATF_TC_HEAD(fifo_hup2,tc)4096dff442fSthorpej ATF_TC_HEAD(fifo_hup2, tc)
4106dff442fSthorpej {
4116dff442fSthorpej 	atf_tc_set_md_var(tc, "descr",
4126dff442fSthorpej 	    "Check POLLHUP behavior with fifos [2]");
4136dff442fSthorpej }
4146dff442fSthorpej 
ATF_TC_BODY(fifo_hup2,tc)4156dff442fSthorpej ATF_TC_BODY(fifo_hup2, tc)
4166dff442fSthorpej {
4176dff442fSthorpej 	struct pollfd pfd;
4186dff442fSthorpej 	int rfd, wfd;
4196dff442fSthorpej 	pid_t pid;
4206dff442fSthorpej 	struct timespec ts1, ts2;
4216dff442fSthorpej 
4226dff442fSthorpej 	fifo_support();
4236dff442fSthorpej 
4246dff442fSthorpej 	ATF_REQUIRE(mkfifo(fifo_path, 0600) == 0);
4256dff442fSthorpej 	ATF_REQUIRE((rfd = open(fifo_path, O_RDONLY | O_NONBLOCK)) >= 0);
4266dff442fSthorpej 	ATF_REQUIRE((wfd = open(fifo_path, O_WRONLY)) >= 0);
4276dff442fSthorpej 
4286dff442fSthorpej 	memset(&pfd, 0, sizeof(pfd));
4296dff442fSthorpej 	pfd.fd = rfd;
4306dff442fSthorpej 	pfd.events = POLLIN;
4316dff442fSthorpej 
4326dff442fSthorpej 	pid = fork();
4336dff442fSthorpej 	ATF_REQUIRE(pid >= 0);
4346dff442fSthorpej 
4356dff442fSthorpej 	if (pid == 0) {
4366dff442fSthorpej 		(void)close(rfd);
4376dff442fSthorpej 		sleep(5);
4386dff442fSthorpej 		(void)close(wfd);
4396dff442fSthorpej 		_exit(0);
4406dff442fSthorpej 	}
4416dff442fSthorpej 	(void)close(wfd);
4426dff442fSthorpej 
4436dff442fSthorpej 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ts1) == 0);
4446dff442fSthorpej 	ATF_REQUIRE(poll(&pfd, 1, INFTIM) == 1);
4456dff442fSthorpej 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ts2) == 0);
4466dff442fSthorpej 
4476dff442fSthorpej 	/* Make sure at least a couple of seconds have elapsed. */
4486dff442fSthorpej 	ATF_REQUIRE(ts2.tv_sec - ts1.tv_sec >= 2);
4496dff442fSthorpej 
4506dff442fSthorpej 	ATF_REQUIRE((pfd.revents & POLLHUP) != 0);
4516dff442fSthorpej }
4526dff442fSthorpej 
ATF_TC_CLEANUP(fifo_hup2,tc)4536dff442fSthorpej ATF_TC_CLEANUP(fifo_hup2, tc)
4546dff442fSthorpej {
4556dff442fSthorpej 	(void)unlink(fifo_path);
4566dff442fSthorpej }
4576dff442fSthorpej 
ATF_TP_ADD_TCS(tp)458068fb4f1Sjruoho ATF_TP_ADD_TCS(tp)
459068fb4f1Sjruoho {
460068fb4f1Sjruoho 
46107e8492eSkamil 	ATF_TP_ADD_TC(tp, 3way);
46207e8492eSkamil 	ATF_TP_ADD_TC(tp, basic);
46307e8492eSkamil 	ATF_TP_ADD_TC(tp, err);
464068fb4f1Sjruoho 
465bad2e9f9Sthorpej 	ATF_TP_ADD_TC(tp, fifo_inout);
4666dff442fSthorpej 	ATF_TP_ADD_TC(tp, fifo_hup1);
4676dff442fSthorpej 	ATF_TP_ADD_TC(tp, fifo_hup2);
4686dff442fSthorpej 
469068fb4f1Sjruoho 	return atf_no_error();
470068fb4f1Sjruoho }
471