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