1 /* 2 * This file is part of poll strace test. 3 * 4 * Copyright (c) 2016 Dmitry V. Levin <ldv (at) altlinux.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include "tests.h" 31 #include <asm/unistd.h> 32 33 #ifdef __NR_poll 34 35 # include <assert.h> 36 # include <errno.h> 37 # include <poll.h> 38 # include <stdio.h> 39 # include <stdlib.h> 40 # include <unistd.h> 41 42 #define PRINT_EVENT(flag, member) \ 43 do { \ 44 if (member & flag) { \ 45 if (member != pfd->member) \ 46 tprintf("|"); \ 47 tprintf(#flag); \ 48 member &= ~flag; \ 49 } \ 50 } while (0) 51 52 static void 53 print_pollfd_entering(const struct pollfd *const pfd) 54 { 55 tprintf("{fd=%d", pfd->fd); 56 if (pfd->fd >= 0) { 57 tprintf(", events="); 58 short events = pfd->events; 59 60 if (pfd->events) { 61 PRINT_EVENT(POLLIN, events); 62 PRINT_EVENT(POLLPRI, events); 63 PRINT_EVENT(POLLOUT, events); 64 #ifdef POLLRDNORM 65 PRINT_EVENT(POLLRDNORM, events); 66 #endif 67 #ifdef POLLWRNORM 68 PRINT_EVENT(POLLWRNORM, events); 69 #endif 70 #ifdef POLLRDBAND 71 PRINT_EVENT(POLLRDBAND, events); 72 #endif 73 #ifdef POLLWRBAND 74 PRINT_EVENT(POLLWRBAND, events); 75 #endif 76 PRINT_EVENT(POLLERR, events); 77 PRINT_EVENT(POLLHUP, events); 78 PRINT_EVENT(POLLNVAL, events); 79 } else 80 tprintf("0"); 81 } 82 tprintf("}"); 83 } 84 85 static void 86 print_pollfd_array_entering(const struct pollfd *const pfd, 87 const unsigned int size, 88 const unsigned int valid, 89 const unsigned int abbrev) 90 { 91 tprintf("["); 92 unsigned int i; 93 for (i = 0; i < size; ++i) { 94 if (i) 95 tprintf(", "); 96 if (i >= valid) { 97 tprintf("%p", &pfd[i]); 98 break; 99 } 100 if (i >= abbrev) { 101 tprintf("..."); 102 break; 103 } 104 print_pollfd_entering(&pfd[i]); 105 } 106 tprintf("]"); 107 } 108 109 static void 110 print_pollfd_exiting(const struct pollfd *const pfd, 111 unsigned int *const seen, 112 const unsigned int abbrev) 113 { 114 if (!pfd->revents || pfd->fd < 0 || *seen > abbrev) 115 return; 116 117 if (*seen) 118 tprintf(", "); 119 ++(*seen); 120 121 if (*seen > abbrev) { 122 tprintf("..."); 123 return; 124 } 125 tprintf("{fd=%d, revents=", pfd->fd); 126 short revents = pfd->revents; 127 128 PRINT_EVENT(POLLIN, revents); 129 PRINT_EVENT(POLLPRI, revents); 130 PRINT_EVENT(POLLOUT, revents); 131 #ifdef POLLRDNORM 132 PRINT_EVENT(POLLRDNORM, revents); 133 #endif 134 #ifdef POLLWRNORM 135 PRINT_EVENT(POLLWRNORM, revents); 136 #endif 137 #ifdef POLLRDBAND 138 PRINT_EVENT(POLLRDBAND, revents); 139 #endif 140 #ifdef POLLWRBAND 141 PRINT_EVENT(POLLWRBAND, revents); 142 #endif 143 PRINT_EVENT(POLLERR, revents); 144 PRINT_EVENT(POLLHUP, revents); 145 PRINT_EVENT(POLLNVAL, revents); 146 tprintf("}"); 147 } 148 149 static void 150 print_pollfd_array_exiting(const struct pollfd *const pfd, 151 const unsigned int size, 152 const unsigned int abbrev) 153 { 154 tprintf("["); 155 unsigned int seen = 0; 156 unsigned int i; 157 for (i = 0; i < size; ++i) 158 print_pollfd_exiting(&pfd[i], &seen, abbrev); 159 tprintf("]"); 160 } 161 162 int 163 main(int ac, char **av) 164 { 165 tprintf("%s", ""); 166 167 assert(syscall(__NR_poll, NULL, 42, 0) == -1); 168 if (ENOSYS == errno) 169 perror_msg_and_skip("poll"); 170 tprintf("poll(NULL, 42, 0) = -1 EFAULT (%m)\n"); 171 172 int fds[2]; 173 if (pipe(fds) || pipe(fds)) 174 perror_msg_and_fail("pipe"); 175 176 const unsigned int abbrev = (ac > 1) ? atoi(av[1]) : -1; 177 const struct pollfd pfds0[] = { 178 { .fd = 0, .events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND }, 179 { .fd = 1, .events = POLLOUT | POLLWRNORM | POLLWRBAND }, 180 { .fd = fds[0], .events = POLLIN | POLLPRI }, 181 { .fd = fds[1], .events = POLLOUT }, 182 { .fd = 2, .events = POLLOUT | POLLWRBAND } 183 }; 184 struct pollfd *const tail_fds0 = tail_memdup(pfds0, sizeof(pfds0)); 185 const int timeout = 42; 186 int rc = syscall(__NR_poll, tail_fds0, 0, timeout); 187 assert(rc == 0); 188 189 tprintf("poll([], 0, %d) = %d (Timeout)\n", timeout, rc); 190 191 rc = syscall(__NR_poll, tail_fds0, ARRAY_SIZE(pfds0), timeout); 192 assert(rc == 3); 193 194 tprintf("poll("); 195 print_pollfd_array_entering(tail_fds0, ARRAY_SIZE(pfds0), 196 ARRAY_SIZE(pfds0), abbrev); 197 tprintf(", %u, %d) = %d (", 198 (unsigned int) ARRAY_SIZE(pfds0), timeout, rc); 199 print_pollfd_array_exiting(tail_fds0, ARRAY_SIZE(pfds0), abbrev); 200 tprintf(")\n"); 201 202 tail_fds0[0].fd = -1; 203 tail_fds0[2].fd = -3; 204 tail_fds0[4].events = 0; 205 rc = syscall(__NR_poll, tail_fds0, ARRAY_SIZE(pfds0), timeout); 206 assert(rc == 2); 207 208 tprintf("poll("); 209 print_pollfd_array_entering(tail_fds0, ARRAY_SIZE(pfds0), 210 ARRAY_SIZE(pfds0), abbrev); 211 tprintf(", %u, %d) = %d (", 212 (unsigned int) ARRAY_SIZE(pfds0), timeout, rc); 213 print_pollfd_array_exiting(tail_fds0, ARRAY_SIZE(pfds0), abbrev); 214 tprintf(")\n"); 215 216 tail_fds0[1].fd = -2; 217 tail_fds0[4].fd = -5; 218 rc = syscall(__NR_poll, tail_fds0, ARRAY_SIZE(pfds0), timeout); 219 assert(rc == 1); 220 221 tprintf("poll("); 222 print_pollfd_array_entering(tail_fds0, ARRAY_SIZE(pfds0), 223 ARRAY_SIZE(pfds0), abbrev); 224 tprintf(", %u, %d) = %d (", 225 (unsigned int) ARRAY_SIZE(pfds0), timeout, rc); 226 print_pollfd_array_exiting(tail_fds0, ARRAY_SIZE(pfds0), abbrev); 227 tprintf(")\n"); 228 229 struct pollfd pfds1[] = { 230 { .fd = 1, .events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND }, 231 { .fd = 0, .events = POLLOUT | POLLWRNORM | POLLWRBAND } 232 }; 233 struct pollfd *const tail_fds1 = tail_memdup(pfds1, sizeof(pfds1)); 234 rc = syscall(__NR_poll, tail_fds1, ARRAY_SIZE(pfds1), timeout); 235 assert(rc == 0); 236 237 tprintf("poll("); 238 print_pollfd_array_entering(tail_fds1, ARRAY_SIZE(pfds1), 239 ARRAY_SIZE(pfds1), abbrev); 240 tprintf(", %u, %d) = %d (Timeout)\n", 241 (unsigned int) ARRAY_SIZE(pfds1), timeout, rc); 242 243 const void *const efault = tail_fds0 + ARRAY_SIZE(pfds0); 244 rc = syscall(__NR_poll, efault, 1, 0); 245 assert(rc == -1); 246 tprintf("poll(%p, 1, 0) = -1 EFAULT (%m)\n", efault); 247 248 const unsigned int valid = 1; 249 const void *const epfds = tail_fds0 + ARRAY_SIZE(pfds0) - valid; 250 rc = syscall(__NR_poll, epfds, valid + 1, 0); 251 assert(rc == -1); 252 tprintf("poll("); 253 print_pollfd_array_entering(epfds, valid + 1, valid, abbrev); 254 errno = EFAULT; 255 tprintf(", %u, 0) = -1 EFAULT (%m)\n", valid + 1); 256 257 tprintf("+++ exited with 0 +++\n"); 258 return 0; 259 } 260 261 #else 262 263 SKIP_MAIN_UNDEFINED("__NR_poll") 264 265 #endif 266