1 /* 2 * Copyright (c) 2004, Bull S.A.. All rights reserved. 3 * Created by: Sebastien Decugis 4 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of version 2 of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it would be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 * 13 * You should have received a copy of the GNU General Public License along 14 * with this program; if not, write the Free Software Foundation, Inc., 15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 17 */ 18 19 /* 20 * The purpose of this file is to provide a monitor process 21 * for the stress/threads/ * / *.c testcases in the OPTS. 22 * 23 * The goal is: 24 * -> if the testcase returns, the monitor returns the error code. 25 * -> after a specified timeout, the monitor let the stress test terminate 26 27 * This allows for the stress tests to be run in an automatic maneer 28 * with a script such as: 29 #!/bin/sh 30 31 #monitor the system 32 vmstat -n 120 180 &> monitor.txt & 33 34 #run the tests 35 for TS in `ls -1 *.c`; 36 do <compile $TS>; 37 if [ $? -eq 0 ]; 38 then <run in background:> 39 helper 6 $TS.exe & 40 fi 41 done 42 43 #wait for the end 44 while [ "`ps -e | grep helper`" ]; 45 do sleep 30; 46 done 47 48 */ 49 50 /* This utility should compile on any POSIX-conformant implementation. */ 51 #define _POSIX_C_SOURCE 200112L 52 53 #include <pthread.h> 54 #include <stdio.h> 55 #include <stdlib.h> 56 #include <unistd.h> 57 #include <signal.h> 58 #include <sys/wait.h> 59 #include <assert.h> 60 #include <time.h> 61 62 pid_t child; 63 int timeout; 64 65 /* Note that there could be a race between 66 the moment the stress test terminates and 67 when the timeout expires. As this is highly 68 improbable, we don't care... */ 69 70 void *timer(void *arg) 71 { 72 int ret = 0; 73 74 unsigned remaining = timeout * 3600; 75 do { 76 remaining = sleep(remaining); 77 } while (remaining); 78 ret = kill(child, SIGUSR1); 79 if (ret != 0) { 80 perror("Failed to kill the stress test"); 81 exit(2); 82 } 83 84 return NULL; 85 } 86 87 int main(int argc, char *argv[]) 88 { 89 int ret; 90 pthread_t th; 91 pid_t chk; 92 int status; 93 char *ts = "[??:??:??]"; 94 struct tm *now; 95 time_t nw; 96 97 /* check args */ 98 if (argc < 3) { 99 printf("\nUsage: \n"); 100 printf(" $ %s n exe arglist\n", argv[0]); 101 printf("\nWhere:\n"); 102 printf(" n is the timeout duration in hours,\n"); 103 printf(" exe is the stress test executable to monitor,\n"); 104 printf 105 (" arglist is the arguments to be passed to executable.\n\n"); 106 return 2; 107 } 108 109 timeout = atoi(argv[1]); 110 if (timeout < 1) { 111 fprintf(stderr, 112 "Invalid timeout value \"%s\". Timeout must be a positive integer.\n", 113 argv[1]); 114 return 2; 115 } 116 117 /* create the timer thread */ 118 ret = pthread_create(&th, NULL, timer, NULL); 119 if (ret != 0) { 120 perror("Failed to create the timeout thread\n"); 121 return 2; 122 } 123 124 /* Create the new process for the stress test */ 125 child = fork(); 126 127 if (child == (pid_t) - 1) { 128 perror("Failed to create a new process"); 129 exit(2); 130 } 131 132 /* The child process executes the test */ 133 if (child == (pid_t) 0) { 134 135 /* Execute the command */ 136 ret = execvp(argv[2], &argv[2]); 137 if (ret == -1) { 138 /* Application was not launched */ 139 perror("Unable to run child application"); 140 return 2; 141 } 142 assert(0); 143 perror("Should not see me"); 144 return 2; 145 } 146 147 /* The parent: */ 148 149 /* wait for the child process to terminate */ 150 chk = waitpid(child, &status, 0); 151 if (chk != child) { 152 perror("Got the wrong process image status"); 153 return 2; 154 } 155 156 /* Cancel the timer thread in case the process returned by itself */ 157 (void)pthread_cancel(th); 158 159 ret = pthread_join(th, NULL); 160 if (ret != 0) { 161 perror("Unable to join the timer thread"); 162 return 2; 163 } 164 165 /* return */ 166 nw = time(NULL); 167 now = localtime(&nw); 168 if (now == NULL) 169 printf(ts); 170 else 171 printf("[%2.2d:%2.2d:%2.2d]", now->tm_hour, now->tm_min, 172 now->tm_sec); 173 if (!WIFEXITED(status)) { 174 printf("The stress sample did not exit\n"); 175 if (WIFSIGNALED(status)) { 176 printf("It was killed with signal %i\n", 177 WTERMSIG(status)); 178 } else { 179 printf("and it was not killed...\n"); 180 } 181 exit(1); 182 } 183 if (WEXITSTATUS(status) == 0) { 184 printf("Test %s PASSED\n", argv[2]); 185 } else { 186 printf("Test %s: returned %d\n", argv[2], WEXITSTATUS(status)); 187 } 188 exit(WEXITSTATUS(status)); 189 } 190