autodriver/autodriver.c
static int monitor_child(pid_t child) {
    int killed = 0;
    int status;

    // create a thread to track the file size at given time interval
    pthread_t timestampThread = 0;  // this thread needs no cancellation
    if (!args.stream && args.timestamp_interval > 0) {
      if (pthread_create(&timestampThread, NULL, timestampFunc, NULL)) {
        ERROR_ERRNO("Failed to create timestamp thread");
        exit(EXIT_OSERROR);
      }
    }

    // Handle the timeout if we have to
    if (args.timeout != 0) {
        struct timespec timeout;
        timeout.tv_sec = args.timeout;
        timeout.tv_nsec = 0;

        int sig_num = sigtimedwait(&sigchld_sigint_set, NULL, &timeout);
        if (sig_num < 0) {
           // Child timed out
           ERROR("Job timed out after %d seconds", args.timeout);
           assert(errno == EAGAIN);
           kill(child, SIGKILL);
           killed = 1;
           childTimedOut = 1;
        }

        // We need to manually run signal handler, since it was blocked.
        if (sig_num == SIGINT) {
            cancel_hndlr(sig_num);
        }
    }

    sigprocmask(SIG_UNBLOCK, &sigint_set, NULL);
    if (waitpid(child, &status, 0) < 0) {
        ERROR_ERRNO("Reaping child");
        exit(EXIT_OSERROR);
    }

    MESSAGE("Test terminates. Duration: %lu seconds", time(NULL) - startTime);

    if (!killed) {
        MESSAGE("Job exited with status %d", WEXITSTATUS(status));
    }

    if (!args.stream && args.timestamp_interval > 0) {
      MESSAGE("Timestamps inserted at %d-second or larger intervals, depending on output rates",
              args.timestamp_interval);
    }
    MESSAGE("Also check end of output for potential errors");

    childFinished = 1;
    dump_output();
    if (childTimedOut) {
      NL_MESSAGE("ERROR Job timed out");  // print error again at the end of output
    }

    cleanup();
    exit(killed ? EXIT_TIMEOUT : EXIT_SUCCESS);
}
/**
 * @brief Monitors the progression of the child
 *
 * SIGCHLD must be blocked when this function is called.
 *
 * @arg child PID of the child process
 * @arg arguments Pointer to argument struct
 *
 * @return Does not return
 */
@brief Monitors the progression of the child
SIGCHLD must be blocked when this function is called.

@arg child PID of the child process
@arg arguments Pointer to argument struct

@return Does not return
@brief Monitors the progression of the child SIGCHLD must be blocked when this function is called . @arg child PID of the child process @arg arguments Pointer to argument struct @return Does not return
static int monitor_child(pid_t child) {
    int killed = 0;
    int status;
    pthread_t timestampThread = 0;  
    if (!args.stream && args.timestamp_interval > 0) {
      if (pthread_create(&timestampThread, NULL, timestampFunc, NULL)) {
        ERROR_ERRNO("Failed to create timestamp thread");
        exit(EXIT_OSERROR);
      }
    }
    if (args.timeout != 0) {
        struct timespec timeout;
        timeout.tv_sec = args.timeout;
        timeout.tv_nsec = 0;
        int sig_num = sigtimedwait(&sigchld_sigint_set, NULL, &timeout);
        if (sig_num < 0) {
           ERROR("Job timed out after %d seconds", args.timeout);
           assert(errno == EAGAIN);
           kill(child, SIGKILL);
           killed = 1;
           childTimedOut = 1;
        }
        if (sig_num == SIGINT) {
            cancel_hndlr(sig_num);
        }
    }
    sigprocmask(SIG_UNBLOCK, &sigint_set, NULL);
    if (waitpid(child, &status, 0) < 0) {
        ERROR_ERRNO("Reaping child");
        exit(EXIT_OSERROR);
    }
    MESSAGE("Test terminates. Duration: %lu seconds", time(NULL) - startTime);
    if (!killed) {
        MESSAGE("Job exited with status %d", WEXITSTATUS(status));
    }
    if (!args.stream && args.timestamp_interval > 0) {
      MESSAGE("Timestamps inserted at %d-second or larger intervals, depending on output rates",
              args.timestamp_interval);
    }
    MESSAGE("Also check end of output for potential errors");
    childFinished = 1;
    dump_output();
    if (childTimedOut) {
      NL_MESSAGE("ERROR Job timed out");  
    }
    cleanup();
    exit(killed ? EXIT_TIMEOUT : EXIT_SUCCESS);
}
static int monitor_child ( pid_t child ) { int killed = 0 ; int status ; pthread_t timestampThread = 0 ; if ( ! args . stream && args . timestamp_interval > 0 ) { if ( pthread_create ( & timestampThread , NULL , timestampFunc , NULL ) ) { ERROR_ERRNO ( " " ) ; exit ( EXIT_OSERROR ) ; } } if ( args . timeout != 0 ) { struct timespec timeout ; timeout . tv_sec = args . timeout ; timeout . tv_nsec = 0 ; int sig_num = sigtimedwait ( & sigchld_sigint_set , NULL , & timeout ) ; if ( sig_num < 0 ) { ERROR ( " " , args . timeout ) ; assert ( errno == EAGAIN ) ; kill ( child , SIGKILL ) ; killed = 1 ; childTimedOut = 1 ; } if ( sig_num == SIGINT ) { cancel_hndlr ( sig_num ) ; } } sigprocmask ( SIG_UNBLOCK , & sigint_set , NULL ) ; if ( waitpid ( child , & status , 0 ) < 0 ) { ERROR_ERRNO ( " " ) ; exit ( EXIT_OSERROR ) ; } MESSAGE ( " " , time ( NULL ) - startTime ) ; if ( ! killed ) { MESSAGE ( " " , WEXITSTATUS ( status ) ) ; } if ( ! args . stream && args . timestamp_interval > 0 ) { MESSAGE ( " " , args . timestamp_interval ) ; } MESSAGE ( " " ) ; childFinished = 1 ; dump_output ( ) ; if ( childTimedOut ) { NL_MESSAGE ( " " ) ; } cleanup ( ) ; exit ( killed ? EXIT_TIMEOUT : EXIT_SUCCESS ) ; }
@brief Monitors the progression of the child
 SIGCHLD must be blocked when this function is called.
@brief Monitors the progression of the child SIGCHLD must be blocked when this function is called .
// create a thread to track the file size at given time interval // this thread needs no cancellation // Handle the timeout if we have to // Child timed out // We need to manually run signal handler, since it was blocked. // print error again at the end of output