Changeset 1546 for zzuf/trunk/src/zzuf.c
- Timestamp:
- Jan 3, 2007, 9:43:47 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
zzuf/trunk/src/zzuf.c
r1544 r1546 42 42 43 43 static void spawn_child(char **); 44 static void clean_children(void); 45 static void read_children(void); 46 44 47 static char *merge_regex(char *, char *); 45 48 static char *merge_file(char *, char *); … … 50 53 #endif 51 54 52 st ruct child_list55 static struct child_list 53 56 { 54 57 enum status … … 66 69 time_t date; 67 70 } *child_list; 68 int parallel = 1, child_count = 0; 69 70 int seed = 0; 71 int endseed = 1; 71 static int parallel = 1, child_count = 0; 72 73 static int seed = 0; 74 static int endseed = 1; 75 static int quiet = 0; 76 static int maxbytes = -1; 77 static double maxtime = -1.0; 72 78 73 79 #define ZZUF_FD_SET(fd, p_fdset, maxfd) \ … … 86 92 char **newargv; 87 93 char *parser, *include = NULL, *exclude = NULL; 88 int i, j, quiet = 0, maxbytes = -1, cmdline = 0; 89 double maxtime = -1.0; 94 int i, cmdline = 0; 90 95 91 96 #if defined(HAVE_GETOPT_H) … … 236 241 while(child_count || seed < endseed) 237 242 { 238 struct timeval tv; 239 time_t now = time(NULL); 240 fd_set fdset; 241 int ret, maxfd = 0; 242 243 /* Spawn a new child, if necessary */ 243 /* Spawn one new child, if necessary */ 244 244 if(child_count < parallel && seed < endseed) 245 245 spawn_child(newargv); 246 246 247 /* Terminate children if necessary */ 248 for(i = 0; i < parallel; i++) 249 { 250 if(child_list[i].status == STATUS_RUNNING 251 && maxbytes >= 0 && child_list[i].bytes > maxbytes) 252 { 253 fprintf(stdout, "seed %i: data exceeded, sending SIGTERM\n", 254 child_list[i].seed); 255 kill(child_list[i].pid, SIGTERM); 256 child_list[i].date = now; 257 child_list[i].status = STATUS_SIGTERM; 258 } 259 260 if(child_list[i].status == STATUS_RUNNING 261 && maxtime >= 0.0 262 && difftime(now, child_list[i].date) > maxtime) 263 { 264 fprintf(stdout, "seed %i: time exceeded, sending SIGTERM\n", 265 child_list[i].seed); 266 kill(child_list[i].pid, SIGTERM); 267 child_list[i].date = now; 268 child_list[i].status = STATUS_SIGTERM; 269 } 270 } 271 272 /* Kill children if necessary */ 273 for(i = 0; i < parallel; i++) 274 { 275 if(child_list[i].status == STATUS_SIGTERM 276 && difftime(now, child_list[i].date) > 2.0) 277 { 278 fprintf(stdout, "seed %i: not responding, sending SIGKILL\n", 279 child_list[i].seed); 280 kill(child_list[i].pid, SIGKILL); 281 child_list[i].status = STATUS_SIGKILL; 282 } 283 } 284 285 /* Collect dead children */ 286 for(i = 0; i < parallel; i++) 287 { 288 int status; 289 pid_t pid; 290 291 if(child_list[i].status != STATUS_SIGKILL 292 && child_list[i].status != STATUS_SIGTERM 293 && child_list[i].status != STATUS_EOF) 294 continue; 295 296 pid = waitpid(child_list[i].pid, &status, WNOHANG); 297 if(pid <= 0) 298 continue; 299 300 if(WIFEXITED(status) && WEXITSTATUS(status)) 301 fprintf(stdout, "seed %i: exit %i\n", 302 child_list[i].seed, WEXITSTATUS(status)); 303 else if(WIFSIGNALED(status)) 304 fprintf(stdout, "seed %i: signal %i\n", 305 child_list[i].seed, WTERMSIG(status)); 306 307 for(j = 0; j < 3; j++) 308 if(child_list[i].fd[j] >= 0) 309 close(child_list[i].fd[j]); 310 311 child_list[i].status = STATUS_FREE; 312 child_count--; 313 } 314 315 fflush(stdout); 316 317 /* Read data from all sockets */ 318 FD_ZERO(&fdset); 319 for(i = 0; i < parallel; i++) 320 { 321 if(child_list[i].status != STATUS_RUNNING) 322 continue; 323 324 for(j = 0; j < 3; j++) 325 ZZUF_FD_SET(child_list[i].fd[j], &fdset, maxfd); 326 } 327 tv.tv_sec = 0; 328 tv.tv_usec = 1000; 329 330 ret = select(maxfd + 1, &fdset, NULL, NULL, &tv); 331 if(ret < 0) 332 perror("select"); 333 if(ret <= 0) 334 continue; 335 336 /* XXX: cute (i, j) iterating hack */ 337 for(i = 0, j = 0; i < parallel; i += (j == 2), j = (j + 1) % 3) 338 { 339 char buf[BUFSIZ]; 340 341 if(child_list[i].status != STATUS_RUNNING) 342 continue; 343 344 if(!ZZUF_FD_ISSET(child_list[i].fd[j], &fdset)) 345 continue; 346 347 ret = read(child_list[i].fd[j], buf, BUFSIZ - 1); 348 if(ret > 0) 349 { 350 /* We got data */ 351 if(j != 0) 352 child_list[i].bytes += ret; 353 if(!quiet || j == 0) 354 write((j < 2) ? STDERR_FILENO : STDOUT_FILENO, buf, ret); 355 } 356 else if(ret == 0) 357 { 358 /* End of file reached */ 359 close(child_list[i].fd[j]); 360 child_list[i].fd[j] = -1; 361 362 if(child_list[i].fd[0] == -1 && child_list[i].fd[1] == -1 363 && child_list[i].fd[2] == -1) 364 child_list[i].status = STATUS_EOF; 365 } 366 } 247 /* Cleanup dead or dying children */ 248 clean_children(); 249 250 /* Read data from children */ 251 read_children(); 367 252 } 368 253 … … 481 366 seed++; 482 367 break; 368 } 369 } 370 371 static void clean_children(void) 372 { 373 time_t now = time(NULL); 374 int i, j; 375 376 /* Terminate children if necessary */ 377 for(i = 0; i < parallel; i++) 378 { 379 if(child_list[i].status == STATUS_RUNNING 380 && maxbytes >= 0 && child_list[i].bytes > maxbytes) 381 { 382 fprintf(stdout, "seed %i: data exceeded, sending SIGTERM\n", 383 child_list[i].seed); 384 kill(child_list[i].pid, SIGTERM); 385 child_list[i].date = now; 386 child_list[i].status = STATUS_SIGTERM; 387 } 388 389 if(child_list[i].status == STATUS_RUNNING 390 && maxtime >= 0.0 391 && difftime(now, child_list[i].date) > maxtime) 392 { 393 fprintf(stdout, "seed %i: time exceeded, sending SIGTERM\n", 394 child_list[i].seed); 395 kill(child_list[i].pid, SIGTERM); 396 child_list[i].date = now; 397 child_list[i].status = STATUS_SIGTERM; 398 } 399 } 400 401 /* Kill children if necessary */ 402 for(i = 0; i < parallel; i++) 403 { 404 if(child_list[i].status == STATUS_SIGTERM 405 && difftime(now, child_list[i].date) > 2.0) 406 { 407 fprintf(stdout, "seed %i: not responding, sending SIGKILL\n", 408 child_list[i].seed); 409 kill(child_list[i].pid, SIGKILL); 410 child_list[i].status = STATUS_SIGKILL; 411 } 412 } 413 414 /* Collect dead children */ 415 for(i = 0; i < parallel; i++) 416 { 417 int status; 418 pid_t pid; 419 420 if(child_list[i].status != STATUS_SIGKILL 421 && child_list[i].status != STATUS_SIGTERM 422 && child_list[i].status != STATUS_EOF) 423 continue; 424 425 pid = waitpid(child_list[i].pid, &status, WNOHANG); 426 if(pid <= 0) 427 continue; 428 429 if(WIFEXITED(status) && WEXITSTATUS(status)) 430 fprintf(stdout, "seed %i: exit %i\n", 431 child_list[i].seed, WEXITSTATUS(status)); 432 else if(WIFSIGNALED(status)) 433 fprintf(stdout, "seed %i: signal %i\n", 434 child_list[i].seed, WTERMSIG(status)); 435 436 for(j = 0; j < 3; j++) 437 if(child_list[i].fd[j] >= 0) 438 close(child_list[i].fd[j]); 439 440 child_list[i].status = STATUS_FREE; 441 child_count--; 442 } 443 444 fflush(stdout); 445 } 446 447 static void read_children(void) 448 { 449 struct timeval tv; 450 fd_set fdset; 451 int i, j, ret, maxfd = 0; 452 453 /* Read data from all sockets */ 454 FD_ZERO(&fdset); 455 for(i = 0; i < parallel; i++) 456 { 457 if(child_list[i].status != STATUS_RUNNING) 458 continue; 459 460 for(j = 0; j < 3; j++) 461 ZZUF_FD_SET(child_list[i].fd[j], &fdset, maxfd); 462 } 463 tv.tv_sec = 0; 464 tv.tv_usec = 1000; 465 466 ret = select(maxfd + 1, &fdset, NULL, NULL, &tv); 467 if(ret < 0) 468 perror("select"); 469 if(ret <= 0) 470 return; 471 472 /* XXX: cute (i, j) iterating hack */ 473 for(i = 0, j = 0; i < parallel; i += (j == 2), j = (j + 1) % 3) 474 { 475 char buf[BUFSIZ]; 476 477 if(child_list[i].status != STATUS_RUNNING) 478 continue; 479 480 if(!ZZUF_FD_ISSET(child_list[i].fd[j], &fdset)) 481 continue; 482 483 ret = read(child_list[i].fd[j], buf, BUFSIZ - 1); 484 if(ret > 0) 485 { 486 /* We got data */ 487 if(j != 0) 488 child_list[i].bytes += ret; 489 if(!quiet || j == 0) 490 write((j < 2) ? STDERR_FILENO : STDOUT_FILENO, buf, ret); 491 } 492 else if(ret == 0) 493 { 494 /* End of file reached */ 495 close(child_list[i].fd[j]); 496 child_list[i].fd[j] = -1; 497 498 if(child_list[i].fd[0] == -1 && child_list[i].fd[1] == -1 499 && child_list[i].fd[2] == -1) 500 child_list[i].status = STATUS_EOF; 501 } 483 502 } 484 503 }
Note: See TracChangeset
for help on using the changeset viewer.