Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v4.15-rc5 125 lines 2.2 kB view raw
1/* 2 * Copyright 2013, Michael Ellerman, IBM Corp. 3 * Licensed under GPLv2. 4 */ 5 6#include <errno.h> 7#include <signal.h> 8#include <stdbool.h> 9#include <stdio.h> 10#include <stdlib.h> 11#include <sys/types.h> 12#include <sys/wait.h> 13#include <unistd.h> 14#include <elf.h> 15#include <fcntl.h> 16#include <link.h> 17#include <sys/stat.h> 18 19#include "subunit.h" 20#include "utils.h" 21 22#define KILL_TIMEOUT 5 23 24static uint64_t timeout = 120; 25 26int run_test(int (test_function)(void), char *name) 27{ 28 bool terminated; 29 int rc, status; 30 pid_t pid; 31 32 /* Make sure output is flushed before forking */ 33 fflush(stdout); 34 35 pid = fork(); 36 if (pid == 0) { 37 setpgid(0, 0); 38 exit(test_function()); 39 } else if (pid == -1) { 40 perror("fork"); 41 return 1; 42 } 43 44 setpgid(pid, pid); 45 46 /* Wake us up in timeout seconds */ 47 alarm(timeout); 48 terminated = false; 49 50wait: 51 rc = waitpid(pid, &status, 0); 52 if (rc == -1) { 53 if (errno != EINTR) { 54 printf("unknown error from waitpid\n"); 55 return 1; 56 } 57 58 if (terminated) { 59 printf("!! force killing %s\n", name); 60 kill(-pid, SIGKILL); 61 return 1; 62 } else { 63 printf("!! killing %s\n", name); 64 kill(-pid, SIGTERM); 65 terminated = true; 66 alarm(KILL_TIMEOUT); 67 goto wait; 68 } 69 } 70 71 /* Kill anything else in the process group that is still running */ 72 kill(-pid, SIGTERM); 73 74 if (WIFEXITED(status)) 75 status = WEXITSTATUS(status); 76 else { 77 if (WIFSIGNALED(status)) 78 printf("!! child died by signal %d\n", WTERMSIG(status)); 79 else 80 printf("!! child died by unknown cause\n"); 81 82 status = 1; /* Signal or other */ 83 } 84 85 return status; 86} 87 88static void alarm_handler(int signum) 89{ 90 /* Jut wake us up from waitpid */ 91} 92 93static struct sigaction alarm_action = { 94 .sa_handler = alarm_handler, 95}; 96 97void test_harness_set_timeout(uint64_t time) 98{ 99 timeout = time; 100} 101 102int test_harness(int (test_function)(void), char *name) 103{ 104 int rc; 105 106 test_start(name); 107 test_set_git_version(GIT_VERSION); 108 109 if (sigaction(SIGALRM, &alarm_action, NULL)) { 110 perror("sigaction"); 111 test_error(name); 112 return 1; 113 } 114 115 rc = run_test(test_function, name); 116 117 if (rc == MAGIC_SKIP_RETURN_VALUE) { 118 test_skip(name); 119 /* so that skipped test is not marked as failed */ 120 rc = 0; 121 } else 122 test_finish(name, rc); 123 124 return rc; 125}