123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- /*
- * Copyright 2013, Michael Ellerman, IBM Corp.
- * Licensed under GPLv2.
- */
- #include <errno.h>
- #include <signal.h>
- #include <stdbool.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- #include <unistd.h>
- #include <elf.h>
- #include <fcntl.h>
- #include <link.h>
- #include <sys/stat.h>
- #include "subunit.h"
- #include "utils.h"
- #define KILL_TIMEOUT 5
- static uint64_t timeout = 120;
- int run_test(int (test_function)(void), char *name)
- {
- bool terminated;
- int rc, status;
- pid_t pid;
- /* Make sure output is flushed before forking */
- fflush(stdout);
- pid = fork();
- if (pid == 0) {
- setpgid(0, 0);
- exit(test_function());
- } else if (pid == -1) {
- perror("fork");
- return 1;
- }
- setpgid(pid, pid);
- /* Wake us up in timeout seconds */
- alarm(timeout);
- terminated = false;
- wait:
- rc = waitpid(pid, &status, 0);
- if (rc == -1) {
- if (errno != EINTR) {
- printf("unknown error from waitpid\n");
- return 1;
- }
- if (terminated) {
- printf("!! force killing %s\n", name);
- kill(-pid, SIGKILL);
- return 1;
- } else {
- printf("!! killing %s\n", name);
- kill(-pid, SIGTERM);
- terminated = true;
- alarm(KILL_TIMEOUT);
- goto wait;
- }
- }
- /* Kill anything else in the process group that is still running */
- kill(-pid, SIGTERM);
- if (WIFEXITED(status))
- status = WEXITSTATUS(status);
- else {
- if (WIFSIGNALED(status))
- printf("!! child died by signal %d\n", WTERMSIG(status));
- else
- printf("!! child died by unknown cause\n");
- status = 1; /* Signal or other */
- }
- return status;
- }
- static void sig_handler(int signum)
- {
- /* Just wake us up from waitpid */
- }
- static struct sigaction sig_action = {
- .sa_handler = sig_handler,
- };
- void test_harness_set_timeout(uint64_t time)
- {
- timeout = time;
- }
- int test_harness(int (test_function)(void), char *name)
- {
- int rc;
- test_start(name);
- test_set_git_version(GIT_VERSION);
- if (sigaction(SIGINT, &sig_action, NULL)) {
- perror("sigaction (sigint)");
- test_error(name);
- return 1;
- }
- if (sigaction(SIGALRM, &sig_action, NULL)) {
- perror("sigaction (sigalrm)");
- test_error(name);
- return 1;
- }
- rc = run_test(test_function, name);
- if (rc == MAGIC_SKIP_RETURN_VALUE) {
- test_skip(name);
- /* so that skipped test is not marked as failed */
- rc = 0;
- } else
- test_finish(name, rc);
- return rc;
- }
|