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., 59 15 * Temple Place - Suite 330, Boston MA 02111-1307, 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 32vmstat -n 120 180 &> monitor.txt & 33 34#run the tests 35for TS in `ls -1 *.c`; 36do <compile $TS>; 37if [ $? -eq 0 ]; 38then <run in background:> 39 helper 6 $TS.exe & 40fi 41done 42 43#wait for the end 44while [ "`ps -e | grep helper`" ]; 45do sleep 30; 46done 47 48*/ 49 50 51/* This utility should compile on any POSIX-conformant implementation. */ 52#define _POSIX_C_SOURCE 200112L 53 54#include <pthread.h> 55#include <stdio.h> 56#include <stdlib.h> 57#include <unistd.h> 58#include <signal.h> 59#include <sys/wait.h> 60#include <assert.h> 61#include <time.h> 62 63pid_t child; 64int timeout; 65 66/* Note that there could be a race between 67the moment the stress test terminates and 68when the timeout expires. As this is highly 69improbable, we don't care... */ 70 71void * timer(void * arg) 72{ 73 int ret=0; 74 75 unsigned remaining = timeout * 3600; 76 do { 77 remaining = sleep(remaining); 78 } while (remaining); 79 ret = kill(child, SIGUSR1); 80 if (ret != 0) 81 { 82 perror("Failed to kill the stress test"); 83 exit(2); 84 } 85 86 return NULL; 87} 88 89 90int main (int argc, char * argv[]) 91{ 92 int ret; 93 pthread_t th; 94 pid_t chk; 95 int status; 96 char *ts="[??:??:??]"; 97 struct tm * now; 98 time_t nw; 99 100 /* check args */ 101 if (argc < 3) 102 { 103 printf("\nUsage: \n"); 104 printf(" $ %s n exe arglist\n", argv[0]); 105 printf("\nWhere:\n"); 106 printf(" n is the timeout duration in hours,\n"); 107 printf(" exe is the stress test executable to monitor,\n"); 108 printf(" arglist is the arguments to be passed to executable.\n\n"); 109 return 2; 110 } 111 112 timeout = atoi(argv[1]); 113 if (timeout < 1) 114 { 115 fprintf(stderr, "Invalid timeout value \"%s\". Timeout must be a positive integer.\n", argv[1]); 116 return 2; 117 } 118 119 /* create the timer thread */ 120 ret = pthread_create(&th, NULL, timer, NULL); 121 if (ret != 0) 122 { 123 perror("Failed to create the timeout thread\n"); 124 return 2; 125 } 126 127 /* Create the new process for the stress test */ 128 child = fork(); 129 130 if (child == (pid_t)-1) 131 { 132 perror("Failed to create a new process"); 133 exit(2); 134 } 135 136 /* The child process executes the test */ 137 if (child == (pid_t)0) 138 { 139 140 /* Execute the command */ 141 ret = execvp(argv[2], &argv[2]); 142 if (ret == -1) 143 { 144 /* Application was not launched */ 145 perror("Unable to run child application"); 146 return 2; 147 } 148 assert(0); 149 perror("Should not see me"); 150 return 2; 151 } 152 153 /* The parent: */ 154 155 /* wait for the child process to terminate */ 156 chk = waitpid(child, &status, 0); 157 if (chk != child) 158 { 159 perror("Got the wrong process image status"); 160 return 2; 161 } 162 163 /* Cancel the timer thread in case the process returned by itself */ 164 (void) pthread_cancel(th); 165 166 ret = pthread_join(th, NULL); 167 if (ret != 0) 168 { 169 perror("Unable to join the timer thread"); 170 return 2; 171 } 172 173 /* return */ 174 nw = time(NULL); 175 now = localtime(&nw); 176 if (now == NULL) 177 printf(ts); 178 else 179 printf("[%2.2d:%2.2d:%2.2d]", now->tm_hour, now->tm_min, now->tm_sec); 180 if ( ! WIFEXITED(status)) 181 { 182 printf("The stress sample did not exit\n"); 183 if (WIFSIGNALED(status)) 184 { 185 printf("It was killed with signal %i\n", WTERMSIG(status)); 186 } 187 else 188 { 189 printf("and it was not killed...\n"); 190 } 191 exit(1); 192 } 193 if (WEXITSTATUS(status) == 0) 194 { 195 printf("Test %s PASSED\n", argv[2]); 196 } 197 else 198 { 199 printf("Test %s: returned %d\n", argv[2], WEXITSTATUS(status)); 200 } 201 exit(WEXITSTATUS(status)); 202} 203 204