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