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 TIMEOUT 120 23 #define KILL_TIMEOUT 5 24 25 26 int 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 50 wait: 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 88 static void alarm_handler(int signum) 89 { 90 /* Jut wake us up from waitpid */ 91 } 92 93 static struct sigaction alarm_action = { 94 .sa_handler = alarm_handler, 95 }; 96 97 int test_harness(int (test_function)(void), char *name) 98 { 99 int rc; 100 101 test_start(name); 102 test_set_git_version(GIT_VERSION); 103 104 if (sigaction(SIGALRM, &alarm_action, NULL)) { 105 perror("sigaction"); 106 test_error(name); 107 return 1; 108 } 109 110 rc = run_test(test_function, name); 111 112 if (rc == MAGIC_SKIP_RETURN_VALUE) 113 test_skip(name); 114 else 115 test_finish(name, rc); 116 117 return rc; 118 } 119 120 static char auxv[4096]; 121 122 void *get_auxv_entry(int type) 123 { 124 ElfW(auxv_t) *p; 125 void *result; 126 ssize_t num; 127 int fd; 128 129 fd = open("/proc/self/auxv", O_RDONLY); 130 if (fd == -1) { 131 perror("open"); 132 return NULL; 133 } 134 135 result = NULL; 136 137 num = read(fd, auxv, sizeof(auxv)); 138 if (num < 0) { 139 perror("read"); 140 goto out; 141 } 142 143 if (num > sizeof(auxv)) { 144 printf("Overflowed auxv buffer\n"); 145 goto out; 146 } 147 148 p = (ElfW(auxv_t) *)auxv; 149 150 while (p->a_type != AT_NULL) { 151 if (p->a_type == type) { 152 result = (void *)p->a_un.a_val; 153 break; 154 } 155 156 p++; 157 } 158 out: 159 close(fd); 160 return result; 161 } 162