1 /*
2 * Copyright (c) Crackerjack Project., 2007-2008 ,Hitachi, Ltd
3 * Author(s): Takahiro Yasui <takahiro.yasui.mp@hitachi.com>,
4 * Yumiko Sugita <yumiko.sugita.yf@hitachi.com>,
5 * Satoshi Fujiwara <sa-fuji@sdl.hitachi.co.jp>
6 * Copyright (c) 2016 Linux Test Project
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
16 * the GNU General Public License for more details.
17 */
18
19 #ifndef _GNU_SOURCE
20 #define _GNU_SOURCE
21 #endif
22
23 #include <errno.h>
24 #include <poll.h>
25 #include <signal.h>
26 #include <stdlib.h>
27 #include <sys/types.h>
28 #include <sys/wait.h>
29 #include "linux_syscall_numbers.h"
30 #include "ltp_signal.h"
31 #include "tst_test.h"
32
33 /* Older versions of glibc don't publish this constant's value. */
34 #ifndef POLLRDHUP
35 #define POLLRDHUP 0x2000
36 #endif
37
38 #define TYPE_NAME(x) .ttype = x, .desc = #x
39
40 struct test_case {
41 int ttype; /* test type (enum) */
42 const char *desc; /* test description (name) */
43 int ret; /* expected ret code */
44 int err; /* expected errno code */
45 short expect_revents; /* expected revents value */
46 unsigned int nfds; /* nfds ppoll parameter */
47 sigset_t *sigmask; /* sigmask ppoll parameter */
48 sigset_t *sigmask_cur; /* sigmask set for current process */
49 struct timespec *ts; /* ts ppoll parameter */
50 struct pollfd *fds; /* fds ppoll parameter */
51 int sigint_count; /* if > 0, spawn process to send SIGINT */
52 /* 'count' times to current process */
53 unsigned int sigint_delay; /* delay between SIGINT signals */
54 };
55
56 enum test_type {
57 NORMAL,
58 MASK_SIGNAL,
59 TIMEOUT,
60 FD_ALREADY_CLOSED,
61 SEND_SIGINT,
62 SEND_SIGINT_RACE_TEST,
63 INVALID_NFDS,
64 INVALID_FDS,
65 };
66
67 static int fd1 = -1;
68 static sigset_t sigmask_empty, sigmask_sigint;
69 static struct pollfd fds_good[1], fds_already_closed[1];
70
71 static struct timespec ts_short = {
72 .tv_sec = 0,
73 .tv_nsec = 200000000,
74 };
75 static struct timespec ts_long = {
76 .tv_sec = 2,
77 .tv_nsec = 0,
78 };
79
80 /* Test cases
81 *
82 * test status of errors on man page
83 *
84 * EBADF can't check because EBADF never happen even though
85 * fd was invalid. In this case, information of invalid
86 * fd is set in revents
87 * EFAULT v ('fds' array in the invalid address space)
88 * EINTR v (a non blocked signal was caught)
89 * EINVAL v ('nfds' is over the 'RLIMIT_NOFILE' value)
90 * ENOMEM can't check because it's difficult to create no-memory
91 */
92
93 static struct test_case tcase[] = {
94 {
95 TYPE_NAME(NORMAL),
96 .expect_revents = POLLIN | POLLOUT,
97 .ret = 1,
98 .err = 0,
99 .nfds = 1,
100 .ts = &ts_long,
101 .fds = fds_good,
102 },
103 {
104 TYPE_NAME(MASK_SIGNAL),
105 .ret = 0,
106 .err = 0,
107 .nfds = 0,
108 .sigmask = &sigmask_sigint,
109 .ts = &ts_short,
110 .fds = fds_good,
111 .sigint_count = 4,
112 .sigint_delay = 100000,
113 },
114 {
115 TYPE_NAME(TIMEOUT),
116 .ret = 0,
117 .err = 0,
118 .nfds = 0,
119 .ts = &ts_short,
120 .fds = fds_good,
121 },
122 {
123 TYPE_NAME(FD_ALREADY_CLOSED),
124 .expect_revents = POLLNVAL,
125 .ret = 1,
126 .err = 0,
127 .nfds = 1,
128 .ts = &ts_long,
129 .fds = fds_already_closed,
130 },
131 {
132 TYPE_NAME(SEND_SIGINT),
133 .ret = -1,
134 .err = EINTR,
135 .nfds = 0,
136 .ts = &ts_long,
137 .fds = fds_good,
138 .sigint_count = 40,
139 .sigint_delay = 100000,
140 },
141 {
142 TYPE_NAME(SEND_SIGINT_RACE_TEST),
143 .ret = -1,
144 .err = EINTR,
145 .nfds = 0,
146 .sigmask = &sigmask_empty,
147 .sigmask_cur = &sigmask_sigint,
148 .ts = &ts_long,
149 .fds = fds_good,
150 .sigint_count = 1,
151 .sigint_delay = 0,
152 },
153 {
154 TYPE_NAME(INVALID_NFDS),
155 .ret = -1,
156 .err = EINVAL,
157 .nfds = -1,
158 .ts = &ts_long,
159 .fds = fds_good,
160 },
161 {
162 TYPE_NAME(INVALID_FDS),
163 .ret = -1,
164 .err = EFAULT,
165 .nfds = 1,
166 .ts = &ts_long,
167 .fds = (struct pollfd *) -1,
168 },
169 };
170
sighandler(int sig LTP_ATTRIBUTE_UNUSED)171 static void sighandler(int sig LTP_ATTRIBUTE_UNUSED)
172 {
173 }
174
setup(void)175 static void setup(void)
176 {
177 int fd2;
178
179 SAFE_SIGNAL(SIGINT, sighandler);
180
181 if (sigemptyset(&sigmask_empty) == -1)
182 tst_brk(TBROK | TERRNO, "sigemptyset");
183 if (sigemptyset(&sigmask_sigint) == -1)
184 tst_brk(TBROK | TERRNO, "sigemptyset");
185 if (sigaddset(&sigmask_sigint, SIGINT) == -1)
186 tst_brk(TBROK | TERRNO, "sigaddset");
187
188 fd1 = SAFE_OPEN("testfile1", O_CREAT | O_EXCL | O_RDWR,
189 S_IRUSR | S_IWUSR);
190 fds_good[0].fd = fd1;
191 fds_good[0].events = POLLIN | POLLPRI | POLLOUT | POLLRDHUP;
192 fds_good[0].revents = 0;
193
194 fd2 = SAFE_OPEN("testfile2", O_CREAT | O_EXCL | O_RDWR,
195 S_IRUSR | S_IWUSR);
196 fds_already_closed[0].fd = fd2;
197 fds_already_closed[0].events = POLLIN | POLLPRI | POLLOUT | POLLRDHUP;
198 fds_already_closed[0].revents = 0;
199 SAFE_CLOSE(fd2);
200 }
201
cleanup(void)202 static void cleanup(void)
203 {
204 if (fd1 != -1)
205 close(fd1);
206 }
207
create_sig_proc(int sig,int count,unsigned int usec)208 static pid_t create_sig_proc(int sig, int count, unsigned int usec)
209 {
210 pid_t pid, cpid;
211
212 pid = getpid();
213 cpid = SAFE_FORK();
214
215 if (cpid == 0) {
216 while (count-- > 0) {
217 usleep(usec);
218 if (kill(pid, sig) == -1)
219 break;
220 }
221 exit(0);
222 }
223
224 return cpid;
225 }
226
do_test(unsigned int i)227 static void do_test(unsigned int i)
228 {
229 pid_t pid = 0;
230 int sys_ret, sys_errno = 0, dummy;
231 struct test_case *tc = &tcase[i];
232
233 tst_res(TINFO, "case %s", tc->desc);
234
235 /* setup */
236 if (tc->sigmask_cur) {
237 if (sigprocmask(SIG_SETMASK, tc->sigmask_cur, NULL) == -1)
238 tst_brk(TBROK, "sigprocmask");
239 }
240 if (tc->sigint_count > 0) {
241 pid = create_sig_proc(SIGINT, tc->sigint_count,
242 tc->sigint_delay);
243 }
244
245 /* test */
246 sys_ret = tst_syscall(__NR_ppoll, tc->fds, tc->nfds, tc->ts,
247 tc->sigmask, SIGSETSIZE);
248 sys_errno = errno;
249
250 /* cleanup */
251 if (tc->sigmask_cur) {
252 if (sigprocmask(SIG_SETMASK, &sigmask_empty, NULL) == -1)
253 tst_brk(TBROK, "sigprocmask");
254 }
255 if (pid > 0) {
256 kill(pid, SIGTERM);
257 SAFE_WAIT(&dummy);
258 }
259
260 /* result check */
261 if (tc->expect_revents) {
262 if (tc->fds[0].revents == tc->expect_revents)
263 tst_res(TPASS, "revents=0x%04x", tc->expect_revents);
264 else
265 tst_res(TFAIL, "revents=0x%04x, expected=0x%04x",
266 tc->fds[0].revents, tc->expect_revents);
267 }
268 if (tc->ret >= 0 && tc->ret == sys_ret) {
269 tst_res(TPASS, "ret: %d", sys_ret);
270 } else if (tc->ret == -1 && sys_ret == -1 && sys_errno == tc->err) {
271 tst_res(TPASS, "ret: %d, errno: %s (%d)", sys_ret,
272 tst_strerrno(sys_errno), sys_errno);
273 } else {
274 tst_res(TFAIL, "ret: %d, exp: %d, ret_errno: %s (%d),"
275 " exp_errno: %s (%d)", tc->ret, sys_ret,
276 tst_strerrno(sys_errno), sys_errno,
277 tst_strerrno(tc->err), tc->err);
278 }
279 }
280
281 static struct tst_test test = {
282 .tid = "ppoll01",
283 .tcnt = ARRAY_SIZE(tcase),
284 .test = do_test,
285 .setup = setup,
286 .cleanup = cleanup,
287 .forks_child = 1,
288 .needs_tmpdir = 1,
289 };
290