| 400 | */ |
| 401 | |
| 402 | void exec_wait() |
| 403 | { |
| 404 | int finished = 0; |
| 405 | |
| 406 | /* Process children that signaled. */ |
| 407 | while ( !finished ) |
| 408 | { |
| 409 | int i; |
| 410 | struct timeval tv; |
| 411 | struct timeval * ptv = NULL; |
| 412 | int select_timeout = globs.timeout; |
| 413 | |
| 414 | /* Prepare file descriptor information for use in select(). */ |
| 415 | fd_set fds; |
| 416 | int const fd_max = populate_file_descriptors( &fds ); |
| 417 | |
| 418 | /* Check for timeouts: |
| 419 | * - kill children that already timed out |
| 420 | * - decide how long until the next one times out |
| 421 | */ |
| 422 | if ( globs.timeout > 0 ) |
| 423 | { |
| 424 | struct tms buf; |
| 425 | clock_t const current = times( &buf ); |
| 426 | for ( i = 0; i < globs.jobs; ++i ) |
| 427 | if ( cmdtab[ i ].pid ) |
| 428 | { |
| 429 | clock_t const consumed = |
| 430 | ( current - cmdtab[ i ].start_time ) / tps; |
| 431 | if ( consumed >= globs.timeout ) |
| 432 | { |
| 433 | killpg( cmdtab[ i ].pid, SIGKILL ); |
| 434 | cmdtab[ i ].exit_reason = EXIT_TIMEOUT; |
| 435 | } |
| 436 | else if ( globs.timeout - consumed < select_timeout ) |
| 437 | select_timeout = globs.timeout - consumed; |
| 438 | } |
| 439 | |
| 440 | /* If nothing else causes our select() call to exit, force it after |
| 441 | * however long it takes for the next one of our child processes to |
| 442 | * crossed its alloted processing time so we can terminate it. |
| 443 | */ |
| 444 | tv.tv_sec = select_timeout; |
| 445 | tv.tv_usec = 0; |
| 446 | ptv = &tv; |
| 447 | } |
| 448 | |
| 449 | /* select() will wait for I/O on a descriptor, a signal, or timeout. */ |
| 450 | { |
| 451 | int ret; |
| 452 | while ( ( ret = select( fd_max + 1, &fds, 0, 0, ptv ) ) == -1 ) |
| 453 | if ( errno != EINTR ) |
| 454 | break; |
| 455 | if ( ret <= 0 ) |
| 456 | continue; |
| 457 | } |
| 458 | |
| 459 | for ( i = 0; i < globs.jobs; ++i ) |
nothing calls this directly
no test coverage detected