1 /* Tests for interrupting VFS calls - by D.C. van Moolenbroek */ 2 /* This test needs to be run as root; otherwise, openpty() won't work. */ 3 #include <stdio.h> 4 #include <sys/time.h> 5 #include <sys/wait.h> 6 #include <sys/socket.h> 7 #include <sys/utsname.h> 8 #include <sys/syslimits.h> 9 #include <netinet/in.h> 10 #include <signal.h> 11 #include <unistd.h> 12 #include <fcntl.h> 13 #include <errno.h> 14 #include <util.h> 15 16 #define ITERATIONS 1 17 18 #include "common.h" 19 20 /* 21 * This signal handler does nothing. It just needs to be triggered, so that 22 * PM will tell VFS to unpause this process. 23 */ 24 static void dummy_handler(int sig) 25 { 26 /* Nothing. */ 27 } 28 29 /* 30 * Interrupt a select(2) call. 31 */ 32 static void 33 test76a(void) 34 { 35 struct sigaction act, oact; 36 struct itimerval it; 37 struct sockaddr_in sin; 38 struct timeval tv; 39 fd_set set; 40 int tfd[2], pfd[2], sfd, maxfd; 41 42 subtest = 1; 43 44 act.sa_handler = dummy_handler; 45 sigfillset(&act.sa_mask); 46 act.sa_flags = 0; 47 if (sigaction(SIGALRM, &act, &oact) < 0) e(1); 48 49 memset(&it, 0, sizeof(it)); 50 it.it_value.tv_sec = 0; 51 it.it_value.tv_usec = 10000; 52 if (setitimer(ITIMER_REAL, &it, NULL) < 0) e(2); 53 54 /* First try without any file descriptors. */ 55 tv.tv_sec = 1; 56 tv.tv_usec = 0; 57 if (select(0, NULL, NULL, NULL, &tv) >= 0) e(3); 58 if (errno != EINTR) e(4); 59 60 /* Then try with different types of file descriptors, all blocking. */ 61 if (openpty(&tfd[0], &tfd[1], NULL, NULL, NULL) < 0) e(5); 62 63 FD_ZERO(&set); 64 FD_SET(tfd[0], &set); /* reading from the PTY master should block */ 65 maxfd = tfd[0]; 66 67 if (pipe(pfd) < 0) e(6); 68 FD_SET(pfd[0], &set); /* reading from an empty pipe should block */ 69 if (maxfd < pfd[0]) maxfd = pfd[0]; 70 71 if ((sfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) e(7); 72 73 memset(&sin, 0, sizeof(sin)); 74 sin.sin_family = AF_INET; 75 /* Binding to an arbitrary port is fine. */ 76 if (bind(sfd, (struct sockaddr *)&sin, sizeof(sin)) < 0) e(8); 77 78 if (listen(sfd, 1) < 0) e(9); 79 80 FD_SET(sfd, &set); /* reading from a listening socket should block */ 81 if (maxfd < sfd) maxfd = sfd; 82 83 memset(&it, 0, sizeof(it)); 84 it.it_value.tv_sec = 0; 85 it.it_value.tv_usec = 100000; 86 if (setitimer(ITIMER_REAL, &it, NULL) < 0) e(10); 87 88 tv.tv_sec = 1; 89 tv.tv_usec = 0; 90 if (select(maxfd + 1, &set, NULL, NULL, &tv) >= 0) e(11); 91 if (errno != EINTR) e(12); 92 93 if (close(tfd[0]) < 0) e(13); 94 if (close(tfd[1]) < 0) e(14); 95 if (close(pfd[0]) < 0) e(15); 96 if (close(pfd[1]) < 0) e(16); 97 if (close(sfd) < 0) e(17); 98 99 if (sigaction(SIGUSR1, &oact, NULL) < 0) e(18); 100 } 101 102 /* 103 * Interrupt reads and writes to a pipe. POSIX states that if the operation 104 * was partially successful, the number of bytes written so far should be 105 * returned; otherwise, the we should get the normal EINTR. 106 */ 107 static void 108 test76b(void) 109 { 110 struct sigaction act, oact; 111 struct itimerval it; 112 char *buf; 113 int pfd[2]; 114 115 subtest = 2; 116 117 if ((buf = malloc(PIPE_BUF * 2)) == NULL) e(1); 118 119 if (pipe(pfd) < 0) e(2); 120 121 act.sa_handler = dummy_handler; 122 sigfillset(&act.sa_mask); 123 act.sa_flags = 0; 124 if (sigaction(SIGALRM, &act, &oact) < 0) e(3); 125 126 memset(&it, 0, sizeof(it)); 127 it.it_value.tv_sec = 0; 128 it.it_value.tv_usec = 10000; 129 if (setitimer(ITIMER_REAL, &it, NULL) < 0) e(4); 130 131 /* 132 * This write is too large for the pipe, so it will block until the 133 * signal arrives. When being interrupted, it should return the pipe 134 * size, as that is the part that has been filled successfully so far. 135 */ 136 if (write(pfd[1], buf, PIPE_BUF * 2) != PIPE_BUF) e(5); 137 138 /* 139 * Since the write partially succeeded, we should be able to read all 140 * we wrote so far, without blocking. 141 */ 142 if (read(pfd[0], buf, PIPE_BUF) != PIPE_BUF) e(6); 143 144 /* We should now be able to fill the pipe up to its full size again. */ 145 if (write(pfd[1], buf, PIPE_BUF) != PIPE_BUF) e(7); 146 147 memset(&it, 0, sizeof(it)); 148 it.it_value.tv_sec = 0; 149 it.it_value.tv_usec = 10000; 150 if (setitimer(ITIMER_REAL, &it, NULL) < 0) e(8); 151 152 /* Now interrupt a write attempt on a full pipe. */ 153 if (write(pfd[1], buf, 1) >= 0) e(9); 154 if (errno != EINTR) e(10); 155 156 /* Empty the pipe again. */ 157 if (read(pfd[0], buf, PIPE_BUF) != PIPE_BUF) e(11); 158 159 memset(&it, 0, sizeof(it)); 160 it.it_value.tv_sec = 0; 161 it.it_value.tv_usec = 10000; 162 if (setitimer(ITIMER_REAL, &it, NULL) < 0) e(12); 163 164 /* Now interrupt a read on an empty pipe. */ 165 if (read(pfd[0], buf, PIPE_BUF) >= 0) e(13); 166 if (errno != EINTR) e(14); 167 168 if (close(pfd[0]) < 0) e(15); 169 if (close(pfd[1]) < 0) e(16); 170 171 if (sigaction(SIGUSR1, &oact, NULL) < 0) e(17); 172 173 free(buf); 174 } 175 176 /* 177 * Interrupt an ioctl(2) call. We use an alarm to interrupt an accept(3) call 178 * on a TCP socket - the accept procedure is (currently) implemented using 179 * ioctl(2) calls. 180 */ 181 static void 182 test76c(void) 183 { 184 struct sigaction act, oact; 185 struct itimerval it; 186 struct sockaddr_in sin; 187 socklen_t len; 188 int sfd; 189 190 subtest = 3; 191 192 if ((sfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) e(1); 193 194 memset(&sin, 0, sizeof(sin)); 195 sin.sin_family = AF_INET; 196 /* Binding to an arbitrary port is fine. */ 197 if (bind(sfd, (struct sockaddr *)&sin, sizeof(sin)) < 0) e(2); 198 199 if (listen(sfd, 1) < 0) e(3); 200 201 act.sa_handler = dummy_handler; 202 sigfillset(&act.sa_mask); 203 act.sa_flags = 0; 204 if (sigaction(SIGALRM, &act, &oact) < 0) e(4); 205 206 memset(&it, 0, sizeof(it)); 207 it.it_value.tv_sec = 0; 208 it.it_value.tv_usec = 10000; 209 if (setitimer(ITIMER_REAL, &it, NULL) < 0) e(5); 210 211 /* This will block until the timer fires. */ 212 len = sizeof(sin); 213 if (accept(sfd, (struct sockaddr *)&sin, &len) >= 0) e(6); 214 if (errno != EINTR) e(7); 215 216 if (close(sfd) < 0) e(8); 217 218 if (sigaction(SIGUSR1, &oact, NULL) < 0) e(9); 219 } 220 221 /* 222 * Try to trigger semi-concurrent processing of normal system calls and 223 * postponed PM requests for a single process within VFS. 224 */ 225 static void 226 test76d(void) 227 { 228 struct utsname name; 229 struct sigaction act, oact; 230 struct itimerval it; 231 int r, fd, pfd[2], count, status; 232 time_t stime, etime, runtime = 30 /*seconds*/; 233 char buf[3], *pbuf; 234 235 subtest = 4; 236 237 /* This test would kill wimpy platforms such as ARM. */ 238 if (uname(&name) < 0) e(1); 239 if (!strcmp(name.machine, "arm")) return; 240 241 act.sa_handler = dummy_handler; 242 sigfillset(&act.sa_mask); 243 act.sa_flags = 0; 244 if (sigaction(SIGALRM, &act, &oact) < 0) e(2); 245 246 if (pipe(pfd) < 0) e(3); 247 248 /* Pre-fill the pipe. */ 249 if ((pbuf = malloc(PIPE_BUF - 1)) == NULL) e(4); 250 251 if (write(pfd[1], pbuf, PIPE_BUF - 1) != PIPE_BUF - 1) e(5); 252 253 free(pbuf); 254 255 switch (fork()) { 256 case 0: 257 if (close(pfd[1]) < 0) e(6); 258 259 /* Read from the pipe, but more slowly than the writer. */ 260 while ((r = read(pfd[0], buf, 2)) != 0) 261 if (r < 0) e(7); 262 263 exit(0); 264 case -1: 265 e(8); 266 default: 267 break; 268 } 269 270 switch (fork()) { 271 case 0: 272 if (close(pfd[0]) < 0) e(9); 273 274 time(&stime); 275 276 /* Start an alarm mayhem. */ 277 it.it_value.tv_sec = 0; 278 it.it_value.tv_usec = 1; 279 it.it_interval.tv_sec = 0; 280 it.it_interval.tv_usec = 1; 281 if (setitimer(ITIMER_REAL, &it, NULL) < 0) e(10); 282 283 /* 284 * Then start writing to the pipe, in such a way that the 285 * write operation will be suspended in every so many cases. 286 */ 287 do { 288 if (write(pfd[1], buf, 3) < 0 && errno != EINTR) 289 e(11); 290 291 time(&etime); 292 } while ((int)(etime - stime) < runtime); 293 294 exit(0); 295 case -1: 296 e(12); 297 default: 298 break; 299 } 300 301 if (close(pfd[0]) < 0) e(13); 302 if (close(pfd[1]) < 0) e(14); 303 304 /* 305 * First give the two processes a while to run regularly. Then start 306 * creating additional noise to keep the VFS worker threads busy. 307 */ 308 runtime /= 2; 309 310 sleep(runtime); 311 312 /* 313 * As of writing, VFS has less than 20 worker threads. Create more 314 * processes than that. 315 */ 316 for (count = 2; count < 20; count++) { 317 switch (fork()) { 318 case 0: 319 time(&stime); 320 321 do { 322 /* 323 * Opening a character device blocks the 324 * calling thread, hopefully causing work to be 325 * queued. Sadly, in practice, the high 326 * priorities of system processes prevent this 327 * case from occurring frequently. It works 328 * better with a driver that has a priority 329 * below that of of user processes. 330 */ 331 if ((fd = open("/dev/null", O_WRONLY)) < 0) 332 e(15); 333 334 close(fd); 335 336 time(&etime); 337 } while ((int)(etime - stime) < runtime); 338 339 exit(0); 340 case -1: 341 e(16); 342 default: 343 break; 344 } 345 } 346 347 /* Wait for all children to shut down. */ 348 while (count-- > 0) { 349 if (wait(&status) <= 0) e(17); 350 if (!WIFEXITED(status)) e(18); 351 if (WEXITSTATUS(status) != 0) e(19); 352 } 353 354 if (sigaction(SIGUSR1, &oact, NULL) < 0) e(20); 355 } 356 357 /* 358 * Try to get a nonblocking select(2) call to be interrupted by a signal. 359 * In the future, VFS should prevent this from happening at all; for now, we 360 * just want to make sure it does not result in disaster when it does happen. 361 */ 362 static void 363 test76e(void) 364 { 365 struct utsname name; 366 struct sigaction act, oact; 367 struct itimerval it; 368 struct timeval tv; 369 fd_set set; 370 int tfd[2], left; 371 372 subtest = 5; 373 374 /* This test would kill wimpy platforms such as ARM. */ 375 if (uname(&name) < 0) e(1); 376 if (!strcmp(name.machine, "arm")) return; 377 378 if (openpty(&tfd[0], &tfd[1], NULL, NULL, NULL) < 0) e(2); 379 380 act.sa_handler = dummy_handler; 381 sigfillset(&act.sa_mask); 382 act.sa_flags = 0; 383 if (sigaction(SIGALRM, &act, &oact) < 0) e(3); 384 385 /* 386 * Start an alarm mayhem. We have to try to get a signal in between 387 * VFS sending a select request to TTY, and TTY replying to VFS with 388 * initial results. 389 */ 390 it.it_value.tv_sec = 0; 391 it.it_value.tv_usec = 1; 392 it.it_interval.tv_sec = 0; 393 it.it_interval.tv_usec = 1; 394 if (setitimer(ITIMER_REAL, &it, NULL) < 0) e(4); 395 396 /* 397 * Now issue nonblocking selects until we get interrupted, or until 398 * we have gone through a hardcoded maximum of attempts. 399 */ 400 left = 100000; 401 do { 402 if (--left == 0) break; 403 404 FD_ZERO(&set); 405 FD_SET(tfd[0], &set); /* reading from master should block */ 406 407 tv.tv_sec = 0; 408 tv.tv_usec = 0; 409 } while (select(2, &set, NULL, NULL, &tv) >= 0); 410 411 if (left > 0 && errno != EINTR) e(5); 412 413 it.it_value.tv_sec = 0; 414 it.it_value.tv_usec = 0; 415 if (setitimer(ITIMER_REAL, &it, NULL) < 0) e(6); 416 417 /* The call failed, so the set must be unmodified. */ 418 if (left > 0 && !FD_SET(tfd[0], &set)) e(7); 419 420 if (close(tfd[0]) < 0) e(8); 421 if (close(tfd[1]) < 0) e(9); 422 423 if (sigaction(SIGUSR1, &oact, NULL) < 0) e(10); 424 } 425 426 int 427 main(int argc, char **argv) 428 { 429 int i, m; 430 431 start(76); 432 433 if (argc == 2) 434 m = atoi(argv[1]); 435 else 436 m = 0xFF; 437 438 for (i = 0; i < ITERATIONS; i++) { 439 if (m & 0x01) test76a(); 440 if (m & 0x02) test76b(); 441 if (m & 0x04) test76c(); 442 if (m & 0x08) test76d(); 443 if (m & 0x10) test76e(); 444 } 445 446 quit(); 447 } 448