xref: /openbsd/regress/lib/libc/sys/t_pollts.c (revision f6aab3d8)
1 /*	$OpenBSD: t_pollts.c,v 1.1 2021/09/02 12:40:44 mbuhl Exp $	*/
2 /*	$NetBSD: t_pollts.c,v 1.1 2020/07/17 15:34:17 kamil Exp $	*/
3 
4 /*-
5  * Copyright (c) 2011, 2020 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Matthias Scheler.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 #include "macros.h"
33 
34 #include <sys/time.h>
35 #include <sys/wait.h>
36 
37 #include "atf-c.h"
38 #include <errno.h>
39 #include <fcntl.h>
40 #include <paths.h>
41 #include <poll.h>
42 #include <stdio.h>
43 #include <signal.h>
44 #include <unistd.h>
45 
46 #ifndef POLLTS
47 #define POLLTS pollts
48 #endif
49 
50 ATF_TC(basic);
51 ATF_TC_HEAD(basic, tc)
52 {
53 	atf_tc_set_md_var(tc, "timeout", "10");
54 	atf_tc_set_md_var(tc, "descr",
55 	    "Basis functionality test for ppoll(2)/pollts(2)");
56 }
57 
58 ATF_TC_BODY(basic, tc)
59 {
60 	int fds[2];
61 	struct pollfd pfds[2];
62 	struct timespec timeout;
63 	int ret;
64 
65 	ATF_REQUIRE_EQ(pipe(fds), 0);
66 
67 	pfds[0].fd = fds[0];
68 	pfds[0].events = POLLIN;
69 	pfds[1].fd = fds[1];
70 	pfds[1].events = POLLOUT;
71 
72 	/* Use a timeout of 1 second. */
73 	timeout.tv_sec = 1;
74 	timeout.tv_nsec = 0;
75 
76 	/*
77 	 * Check that we get a timeout waiting for data on the read end
78 	 * of our pipe.
79 	 */
80 	pfds[0].revents = -1;
81 	pfds[1].revents = -1;
82 	ATF_REQUIRE_EQ_MSG(ret = POLLTS(&pfds[0], 1, &timeout, NULL), 0,
83 	    "got: %d", ret);
84 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
85 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, -1, "got: %d", pfds[1].revents);
86 
87 	/* Check that the write end of the pipe as reported as ready. */
88 	pfds[0].revents = -1;
89 	pfds[1].revents = -1;
90 	ATF_REQUIRE_EQ_MSG(ret = POLLTS(&pfds[1], 1, &timeout, NULL), 1,
91 	    "got: %d", ret);
92 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, -1, "got: %d", pfds[0].revents);
93 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",\
94 	    pfds[1].revents);
95 
96 	/* Check that only the write end of the pipe as reported as ready. */
97 	pfds[0].revents = -1;
98 	pfds[1].revents = -1;
99 	ATF_REQUIRE_EQ_MSG(ret = POLLTS(pfds, 2, &timeout, NULL), 1,
100 	    "got: %d", ret);
101 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
102 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
103 	    pfds[1].revents);
104 
105 	/* Write data to our pipe. */
106 	ATF_REQUIRE_EQ(write(fds[1], "", 1), 1);
107 
108 	/* Check that both ends of our pipe are reported as ready. */
109 	pfds[0].revents = -1;
110 	pfds[1].revents = -1;
111 	ATF_REQUIRE_EQ_MSG(ret = POLLTS(pfds, 2, &timeout, NULL), 2,
112 	    "got: %d", ret);
113 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, POLLIN, "got: %d",
114 	    pfds[0].revents);
115 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
116 	    pfds[1].revents);
117 
118 	ATF_REQUIRE_EQ(close(fds[0]), 0);
119 	ATF_REQUIRE_EQ(close(fds[1]), 0);
120 }
121 
122 ATF_TC(err);
123 ATF_TC_HEAD(err, tc)
124 {
125 	atf_tc_set_md_var(tc, "descr", "Check errors from ppoll(2)/pollts(2)");
126 }
127 
128 ATF_TC_BODY(err, tc)
129 {
130 	struct timespec timeout;
131 	struct pollfd pfd;
132 	int fd = 0;
133 
134 	pfd.fd = fd;
135 	pfd.events = POLLIN;
136 
137 	timeout.tv_sec = 1;
138 	timeout.tv_nsec = 0;
139 
140 	errno = 0;
141 	ATF_REQUIRE_ERRNO(EFAULT, POLLTS((void *)-1, 1, &timeout, NULL) == -1);
142 
143 	timeout.tv_sec = -1;
144 	timeout.tv_nsec = -1;
145 
146 	errno = 0;
147 	ATF_REQUIRE_ERRNO(EINVAL, POLLTS(&pfd, 1, &timeout, NULL) == -1);
148 }
149 
150 ATF_TC(sigmask);
151 ATF_TC_HEAD(sigmask, tc)
152 {
153 	atf_tc_set_md_var(tc, "timeout", "10");
154 	atf_tc_set_md_var(tc, "descr",
155 	    "Check that ppoll(2)/pollts(2) restores the signal mask (PR kern/44986)");
156 }
157 
158 ATF_TC_BODY(sigmask, tc)
159 {
160 	int fd;
161 	struct pollfd pfd;
162 	struct timespec timeout;
163 	sigset_t mask;
164 	int ret;
165 
166 	fd = open(_PATH_DEVNULL, O_RDONLY);
167 	ATF_REQUIRE(fd >= 0);
168 
169 	pfd.fd = fd;
170 	pfd.events = POLLIN;
171 
172 	/* Use a timeout of 1 second. */
173 	timeout.tv_sec = 1;
174 	timeout.tv_nsec = 0;
175 
176 	/* Unblock all signals. */
177 	ATF_REQUIRE_EQ(sigfillset(&mask), 0);
178 	ATF_REQUIRE_EQ(sigprocmask(SIG_UNBLOCK, &mask, NULL), 0);
179 
180 	/*
181 	 * Check that ppoll(2)/pollts(2) immediately returns. We block *all*
182 	 * signals during ppoll(2)/pollts(2).
183 	 */
184 	ATF_REQUIRE_EQ_MSG(ret = POLLTS(&pfd, 1, &timeout, &mask), 1,
185 	    "got: %d", ret);
186 
187 	/* Check that signals are now longer blocked. */
188 	ATF_REQUIRE_EQ(sigprocmask(SIG_SETMASK, NULL, &mask), 0);
189 	ATF_REQUIRE_EQ_MSG(sigismember(&mask, SIGUSR1), 0,
190 	    "signal mask was changed.");
191 
192 	ATF_REQUIRE_EQ(close(fd), 0);
193 }
194 
195 ATF_TP_ADD_TCS(tp)
196 {
197 
198 	ATF_TP_ADD_TC(tp, basic);
199 	ATF_TP_ADD_TC(tp, err);
200 	ATF_TP_ADD_TC(tp, sigmask);
201 
202 	return atf_no_error();
203 }
204