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 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 97int 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 120static char auxv[4096]; 121 122void *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 } 158out: 159 close(fd); 160 return result; 161} 162