Mercurial > projects > dstress
changeset 940:dddc404783c9
added basic Windows support to crashRun.c
NOTE: crashRun.c takes now the arguments "<timeOut> <maxMemory> <command> [command args]" instead of "<command> [command args]"
author | thomask |
---|---|
date | Sat, 01 Apr 2006 20:22:12 +0000 |
parents | 38e8bc3a9a50 |
children | 60f9aece9c62 |
files | crashRun.c dstress.c |
diffstat | 2 files changed, 137 insertions(+), 57 deletions(-) [+] |
line wrap: on
line diff
--- a/crashRun.c Sat Apr 01 20:22:02 2006 +0000 +++ b/crashRun.c Sat Apr 01 20:22:12 2006 +0000 @@ -2,8 +2,9 @@ * crashRun - execute command with restricted CPU time and memory usage * * Copyright (C) - * 2005 Thomas Kuehne <thomas@kuehne.cn> - * 2005 Anders F Björrklund <afb@algonet.se> + * 2005, 2006 Thomas Kuehne <thomas@kuehne.cn> + * 2005 Anders F Björrklund <afb@algonet.se> (BSD) + * 2005 Stewart Gordon <smjg_1998@yahoo.com> (Windows) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,25 +32,39 @@ #include <stdio.h> #include <signal.h> -const int TIME_OUT= 30; /* time-out in seconds (might be cpu or system time)*/ -const int MEM_LIMIT = 1024; /* mem megabytes */ +#undef WAIT_GUARD +#define WAIT_GUARD 3 + +/* time-out in seconds + * Posix: cpu time(timeOut) and system time(timeOut * WAIT_GUARD) + * Windows: system time(timeOut) + */ +long int timeOut; + +/* max memory usage in megabytes (Posix only) */ +long int memoryLimit; /* identify system API */ -#if defined(__GNU_LIBRARY__) || defined(__GLIBC__) || defined(__USE_POSIX) -#define USE_POSIX +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) || defined(_BSD_SOURCE) || defined(_SVID_SOURCE) +#define USE_POSIX 1 +#endif + +#if defined(__GNU_LIBRARY__) || defined(__GLIBC__) +#define USE_POSIX 1 #endif #if defined(linux) || defined(__FreeBsd__) || defined(__OpenBSD__) -#define USE_POSIX +#define USE_POSIX 1 #endif #if defined(__APPLE__) && defined(__MACH__) -#define USE_POSIX +#define USE_POSIX 1 #endif #if !defined(USE_POSIX) && \ - (defined(WINDOWS) || defined(WIN) || defined(WINVER) || defined(WIN32)) -#define USE_WINDOWS + (defined(WINDOWS) || defined(WIN) || defined(WINVER) || defined(WIN32) \ + || defined(WIN64)) +#define USE_WINDOWS 1 #endif @@ -80,82 +95,73 @@ #include <sys/types.h> #endif +#ifdef USE_WINDOWS +#include <windows.h> +#define snprintf _snprintf +#endif -char* cmd; + -/* let's start implementing :) */ +#ifdef USE_POSIX void handleSignal(int signalID){ -#ifdef SIGALARM if( signalID==SIGALRM #ifdef SIGXCPU || signalID==SIGXCPU #endif ) - printf("EXIT CODE: signal %d (time-out after %d seconds)", signalID, TIME_OUT); + printf("EXIT CODE: signal %d (time-out after CPU/total %li/%li seconds)\n", + signalID, timeOut, timeOut * WAIT_GUARD); else -#endif - printf("EXIT CODE: signal %d, errno %d\n", signalID, errno); + printf("EXIT CODE: signal %d, errno %d\n", signalID, errno); fflush(stdout); fflush(stderr); -#ifdef USE_POSIX kill(-pID, SIGTERM); sleep(1); kill(-pID, SIGKILL); -#else -#error sub processes have to be killed -#endif -#ifdef SIGUSR1 - if(signalID==SIGUSR1 || signalID==SIGUSR2) - exit(EXIT_SUCCESS); - else -#endif exit(EXIT_FAILURE); } void setupLimits(){ -#ifdef USE_POSIX_LIMITS struct rlimit limit; - limit.rlim_cur = TIME_OUT; - limit.rlim_max = TIME_OUT; + limit.rlim_cur = timeOut; + limit.rlim_max = timeOut; if(0!=setrlimit(RLIMIT_CPU, &limit)){ fprintf(stderr, "failed to set cpu limit [%d]\n", errno); exit(EXIT_FAILURE); } - limit.rlim_cur = MEM_LIMIT * 1024L * 1024L; - limit.rlim_max = MEM_LIMIT * 1024L * 1024L; + limit.rlim_cur = memoryLimit * 1024L * 1024L; + limit.rlim_max = memoryLimit * 1024L * 1024L; #ifdef RLIMIT_AS if(0!=setrlimit(RLIMIT_AS, &limit)){ - fprintf(stderr, "failed to set mem limit (AS) [%d]\n", errno); + fprintf(stderr, "failed to set mem limit (AS) %s [%d]\n", strerror(errno), errno); exit(EXIT_FAILURE); } #endif if(0!=setrlimit(RLIMIT_DATA, &limit)){ - fprintf(stderr, "failed to set mem limit (DATA) [%d]\n", errno); + fprintf(stderr, "failed to set mem limit (DATA) %s [%d]\n", strerror(errno), errno); exit(EXIT_FAILURE); } if(0!=setrlimit(RLIMIT_RSS, &limit)){ - fprintf(stderr, "failed to set mem limit (RSS) [%d]\n", errno); + fprintf(stderr, "failed to set mem limit (RSS) %s [%d]\n", strerror(errno), errno); exit(EXIT_FAILURE); } #if defined(RLIMIT_MEMLOCK) && !defined(linux) if(0!=setrlimit(RLIMIT_MEMLOCK, &limit)){ - fprintf(stderr, "failed to set mem limit (MEMLOCK) [%d]\n", errno); + fprintf(stderr, "failed to set mem limit (MEMLOCK): %s [%d]\n", strerror(errno), errno); exit(EXIT_FAILURE); } #endif -#endif /* USE_POSIX_LIMITS */ } void setupHandlers(){ -#ifdef USE_POSIX #ifdef SIGHUP signal(SIGHUP, &handleSignal); #endif @@ -185,9 +191,7 @@ #ifdef SIGPIPE signal(SIGPIPE, &handleSignal); #endif -#ifdef SIGALRM signal(SIGALRM, &handleSignal); -#endif signal(SIGTERM, &handleSignal); #ifdef SIGSTKFLT signal(SIGSTKFLT, &handleSignal); @@ -207,26 +211,26 @@ #ifdef SIGSYS signal(SIGSYS, &handleSignal); #endif +} #endif /* USE_POSIX */ -} - -void cleanCommand(){ - free(cmd); -} char* reconstructCmd(int argc, char** argv){ size_t cmdLen=1; size_t tmpLen; size_t i; char* tmp; + char* cmd; for(i=0; i<argc; i++){ cmdLen+=strlen(argv[i]); cmdLen+=3; } - cmd = (char*)malloc(cmdLen); - atexit(&cleanCommand); + cmd = malloc(cmdLen); + if(!cmd){ + fprintf(stderr, "failed to allocate enough memory"); + exit(EXIT_FAILURE); + } *cmd = '\x00'; tmp = cmd; @@ -240,11 +244,35 @@ } int main(int argc, char** argv){ - if(argc<2){ - fprintf(stderr, "name of command to call required\n"); + char* cmd; + char* end; + + if(argc<4){ + fprintf(stderr, "crashRun <timeOut (s)> <maxMemory (MB)> <command> [<command arg> ...]\n"); + return EXIT_FAILURE; + } + timeOut = strtol(argv[1], &end, 10); + if(*end){ + fprintf(stderr, "the timeOut argument contains the illegal character: %c (0x%X)", *end, *end); + return EXIT_FAILURE; + }else if(timeOut < 1){ + fprintf(stderr, "minimum timeOut is 1 second, got %li seconds\n", timeOut); return EXIT_FAILURE; } - cmd = reconstructCmd(argc-1, argv+1); + + memoryLimit = strtol(argv[2], &end, 10); + if(*end){ + fprintf(stderr, "the maxMemory argument contains the illegal character: %c (0x%X)", *end, *end); + return EXIT_FAILURE; + }else if(memoryLimit < 1){ + fprintf(stderr, "minimum memoryLimit is 1MB second, got %li MB\n", memoryLimit); + return EXIT_FAILURE; + } + cmd = reconstructCmd(argc-3, argv+3); + +#ifdef DEBUG + printf("cmd[%li sec, %li MB]: %s \n", timeOut, memoryLimit, cmd); +#endif #ifdef USE_POSIX setupLimits(); @@ -252,9 +280,6 @@ if(pID == 0){ /* child */ pID=setsid(); -#ifdef DEBUG - printf("cmd[%i sec]: %s \n", TIME_OUT, cmd); -#endif printf("EXIT CODE: %d\n", system(cmd)); }else if(pID < 0){ fprintf(stderr, "failed to fork\n"); @@ -263,14 +288,66 @@ /* parent */ setupHandlers(); #if !(defined(USE_POSIX_LIMITS) && defined(SIGXCPU)) - alarm(TIME_OUT); + alarm(timeOut); +#else + /* safe guard against childs without CPU usage */ + alarm(timeOut * WAIT_GUARD); #endif wait(NULL); } return EXIT_SUCCESS; -#else /* USE_POSIX */ +#elif USE_WINDOWS + /* BUG: maxMemory not implemented */ + + PROCESS_INFORMATION processInfo; + STARTUPINFO startupInfo; + SECURITY_ATTRIBUTES sa = { + sizeof(SECURITY_ATTRIBUTES), NULL, TRUE + }; + unsigned long exitCode; + long int timeLeft = timeOut; /* time limit in iterations of WFX loop */ + + memset(&processInfo, 0, sizeof(PROCESS_INFORMATION)); + memset(&startupInfo, 0, sizeof(STARTUPINFO)); + startupInfo.cb = sizeof(STARTUPINFO); + + if (!CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, + &startupInfo, &processInfo)) { + void *message; + + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER + | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, + (char*) &message, 0, NULL); -#error no test run implmentation present for your system + /* this should never happen */ + fprintf(stderr, "ERROR running %s:\n", cmd); + fprintf(stderr, "%s\n", message); + LocalFree((HLOCAL) message); + return RAND_MAX; + } + + /* wait for exit */ + while (TRUE) { + Sleep(1000); + GetExitCodeProcess(processInfo.hProcess, &exitCode); + if (exitCode == 0x103) { + if (--timeLeft == 0) { + TerminateProcess(processInfo.hProcess, EXIT_FAILURE); + printf("EXIT CODE: timeout after %li seconds\n", timeOut); + Sleep(100); + return EXIT_SUCCESS; + } + } else { + printf("EXIT CODE: %i\n", exitCode); + return EXIT_SUCCESS; + } + } + + fprintf(stderr, "crashRun: BUG\n"); + return EXIT_FAILURE; +#else + +#error no implmentation for your system found (supported: Posix, Windows) #endif /* USE_POSIX else */ }
--- a/dstress.c Sat Apr 01 20:22:02 2006 +0000 +++ b/dstress.c Sat Apr 01 20:22:12 2006 +0000 @@ -2,7 +2,10 @@ * core test tool for the DStress test suite * http://dstress.kuehne.cn * - * Copyright (C) 2005, 2006 Thomas Kuehne <thomas@kuehne.cn> + * Copyright (C) + * 2005, 2006 Thomas Kuehne <thomas@kuehne.cn> + * 2005 Carlos Santander (Window files) + * 2005 Stewart Gordon <smjg_1998@yahoo.com> (Window crashRun) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -151,7 +154,7 @@ #define TORTURE_PREFIX "torture-" #ifdef USE_POSIX -#define CRASH_RUN "./crashRun" +#define CRASH_RUN "./crashRun 30 1024" #define TMP_DIR "./obj" #else #ifdef USE_WINDOWS @@ -653,7 +656,7 @@ len = 20 + strlen(CRASH_RUN) + strlen(cmd) + strlen(*logFile); buffer = malloc(len); - snprintf(buffer, len, "\"%s\" %s > %s 2>&1", CRASH_RUN, cmd, *logFile); + snprintf(buffer, len, "%s %s > %s 2>&1", CRASH_RUN, cmd, *logFile); system(buffer); free(buffer);