changeset 545:7b5efee9d724

prepared for windows porting
author thomask
date Tue, 17 May 2005 19:05:41 +0000
parents 19e36f020f57
children f0f1f142bf6d
files crashRun.c
diffstat 1 files changed, 189 insertions(+), 110 deletions(-) [+]
line wrap: on
line diff
--- a/crashRun.c	Tue May 17 16:10:49 2005 +0000
+++ b/crashRun.c	Tue May 17 19:05:41 2005 +0000
@@ -1,8 +1,8 @@
 /*
- * crashRun - execute command with restricted CPU time and memory usage 
+ * crashRun - execute command with restricted CPU time and memory usage
  *
  * Copyright (C)
- * 		2005 Thomas Kuehne <thomas@kuehne.cn>
+ *		2005 Thomas Kuehne <thomas@kuehne.cn>
  *		2005 Anders F Björklund <afb@algonet.se>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -29,11 +29,13 @@
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <signal.h>
 
-/* time-out in minutes (cpu or system time)*/
-const int TIME_OUT=5;
+const int TIME_OUT= 5*60; /* time-out in seconds (might be cpu or system time)*/
+const int MEM_LIMIT = 200;  /* mem megabytes */
 
-#if defined(__GNU_LIBRARY__) || defined(__GLIBC__)
+/* try to cope with -ansi and other threads */
+#if defined(__GNU_LIBRARY__) || defined(__GLIBC__) || defined(__USE_POSIX)
 #define USE_POSIX
 #endif
 
@@ -49,147 +51,224 @@
 #define USE_POSIX
 #endif
 
+#if !defined(USE_POSIX) && \
+	(defined(WINDOWS) || defined(WIN) || defined(WINVER) || defined(WIN32))
+#define USE_WINDOWS
+#endif
 
+
+/* is the environment sane? */
+#if defined(USE_POSIX) && defined(USE_WINDOWS)
+#error USE_WINDOWS and USE_POSIX are defined
+#endif
+
+#if !defined(USE_POSIX) && !defined(USE_WINDOWS)
+#error neither USE_POSIX nor USE_WINDOWS are defined
+#endif
+
+
+/* API inludes and config */
 #ifdef USE_POSIX
-#define USE_LIMIT
-
+#define USE_POSIX_LIMITS
+#include <sys/types.h>
 #include <unistd.h>
 #include <sys/wait.h>
+static pid_t pID;
+#endif
 
-#ifdef USE_LIMIT
+#ifdef USE_POSIX_LIMITS
+#ifndef USE_POSIX
+#error USE_POSIX_LIMITS requires USE_POSIX
+#endif
+#include <sys/resource.h>
 #include <sys/types.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-
-const int PROC_LIMIT = 256; /* no processes */ 
-const int MEM_LIMIT = 200;  /* mem megabytes */
 #endif
 
-static pid_t pID;
+
+/* let's start implementing :) */
 
-void resourceLimit(int signalID){
+void handleSignal(int signalID){
+#ifdef SIGALARM
+	if( signalID==SIGALRM
 #ifdef SIGXCPU
-	if(signalID==SIGALRM || signalID==SIGXCPU){
-#else
-	if(signalID==SIGALRM){
+		|| signalID==SIGXCPU
 #endif
-		printf("EXIT CODE: signal %d (time-out after %d minutes)", signalID, TIME_OUT);
-	}else{
-		printf("EXIT CODE: signal %d\n", signalID);
-	}
+	)
+		printf("EXIT CODE: signal %d (time-out after %d seconds)", signalID, TIME_OUT);
+	else
+#endif
+	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
 
-	if(signalID==SIGUSR1 || signalID==SIGUSR2){
+#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;
+	if(0!=setrlimit(RLIMIT_CPU, &limit)){
+		fprintf(stderr, "failed to set cpu limit [%d]\n", errno);
 		exit(EXIT_FAILURE);
-	}else{
-		exit(EXIT_SUCCESS);
+	}
+
+	limit.rlim_cur = MEM_LIMIT * 1024L * 1024L;
+	limit.rlim_max = MEM_LIMIT * 1024L * 1024L;
+#ifdef RLIMIT_AS
+	if(0!=setrlimit(RLIMIT_AS, &limit)){
+		fprintf(stderr, "failed to set mem limit (AS) [%d]\n", errno);
+		exit(EXIT_FAILURE);
 	}
+#endif
+
+	if(0!=setrlimit(RLIMIT_DATA, &limit)){
+		fprintf(stderr, "failed to set mem limit (DATA) [%d]\n", errno);
+		exit(EXIT_FAILURE);
+	}
+
+	if(0!=setrlimit(RLIMIT_RSS, &limit)){
+		fprintf(stderr, "failed to set mem limit (RSS) [%d]\n", 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);
+		exit(EXIT_FAILURE);
+	}
+#endif
+#endif /* USE_POSIX_LIMITS */
 }
 
-int main(int argc, char** arg){
-#ifdef USE_LIMIT
-	{
-		struct rlimit	limit;
-	
-		limit.rlim_cur = TIME_OUT * 60;
-		limit.rlim_max = TIME_OUT * 60;
-		if(0!=setrlimit(RLIMIT_CPU, &limit)){
-			fprintf(stderr, "failed to set cpu limit [%d]\n", errno);
-			return EXIT_FAILURE;
-		}
-	
-		limit.rlim_cur = PROC_LIMIT;
-		limit.rlim_max = PROC_LIMIT;
-		if(0!=setrlimit(RLIMIT_NPROC, &limit)){
-			fprintf(stderr, "failed to set proc limit [%d]\n", errno);
-			return EXIT_FAILURE;
-		}
-	
-		limit.rlim_cur = MEM_LIMIT * 1024L * 1024L;
-		limit.rlim_max = MEM_LIMIT * 1024L * 1024L;
-#ifdef RLIMIT_AS
-		if(0!=setrlimit(RLIMIT_AS, &limit)){
-			fprintf(stderr, "failed to set mem limit (AS) [%d]\n", errno);
-			return EXIT_FAILURE;
-		}
-#endif /* RLIMIT_AS */
-		
-		if(0!=setrlimit(RLIMIT_DATA, &limit)){
-			fprintf(stderr, "failed to set mem limit (DATA) [%d]\n", errno);
-			return EXIT_FAILURE;
-		}
+void setupHandlers(){
+#ifdef USE_POSIX
+#ifdef SIGHUP
+	signal(SIGHUP, &handleSignal);
+#endif
+	signal(SIGINT, &handleSignal);
+#ifdef SIGQUIT
+	signal(SIGQUIT, &handleSignal);
+#endif
+	signal(SIGILL, &handleSignal);
+#ifdef SIGTRAP
+	signal(SIGTRAP, &handleSignal);
+#endif
+	signal(SIGABRT, &handleSignal);
+#ifdef SIGIOT
+	signal(SIGIOT, &handleSignal);
+#endif
+#ifdef SIGBUS
+	signal(SIGBUS, &handleSignal);
+#endif
+	signal(SIGFPE, &handleSignal);
+#ifdef SIGKILL
+	signal(SIGKILL, &handleSignal);
+#endif
+#ifdef SIGUSR1
+	signal(SIGUSR1, &handleSignal);
+#endif
+	signal(SIGSEGV, &handleSignal);
+#ifdef SIGUSR2
+	signal(SIGUSR2, &handleSignal);
+#endif
+#ifdef SIGPIPE
+	signal(SIGPIPE, &handleSignal);
+#endif
+#ifdef SIGALRM
+	signal(SIGALRM, &handleSignal);
+#endif
+	signal(SIGTERM, &handleSignal);
+#ifdef SIGSTKFLT
+	signal(SIGSTKFLT, &handleSignal);
+#endif
+#ifdef SIGTSTP
+	signal(SIGTSTP, &handleSignal);
+#endif
+#ifdef SIGXCPU
+	signal(SIGXCPU, &handleSignal);
+#endif
+#ifdef SIGXFSZ
+	signal(SIGXFSZ, &handleSignal);
+#endif
+#ifdef SIGVTALRM
+	signal(SIGVTALRM, &handleSignal);
+#endif
+#ifdef SIGSYS
+	signal(SIGSYS, &handleSignal);
+#endif
+#endif /* USE_POSIX */
+}
 
-		if(0!=setrlimit(RLIMIT_RSS, &limit)){
-			fprintf(stderr, "failed to set mem limit (RSS) [%d]\n", errno);
-			return 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);
-			return EXIT_FAILURE;
-		}
-#endif /* RLIMIT_MEMLOCK */
+char* reconstructCmd(int argc, char** argv){
+	int cmdLen=1;
+	int i;
+	char* cmd;
+
+	for(i=0; i<argc; i++){
+		cmdLen+=strlen(argv[i]);
+		cmdLen+=3;
 	}
-#endif /* USE_LIMIT */
-	pID = fork();
-	if (pID == 0){
-		/* child: resource management */
-		pID=setsid();
+
+	cmd = (char*)malloc(cmdLen);
+	*cmd = '\x00';
 
-		/* child: execute args */
-		int cmdLen=1;
-		int i;
-		for(i=1; i<argc; i++){
-			cmdLen+=strlen(arg[i]);
-			cmdLen+=3;
-		}
+	for(i=0; i<argc; i++){
+		strcat(cmd, "\"");
+		strcat(cmd, argv[i]);
+		strcat(cmd, "\" ");
+	}
+	return cmd;
+}
 
-		char* cmd = malloc(cmdLen);
-		*cmd='\x00';
-	
-		for(i=1; i<argc; i++){
-			strcat(cmd, "\"");
-			strcat(cmd, arg[i]);
-			strcat(cmd, "\" ");
-		}
+int main(int argc, char** argv){
+	char* cmd;
+	if(argc<2){
+		fprintf(stderr, "name of command to call required\n");
+		return EXIT_FAILURE;
+	}
+	cmd = reconstructCmd(argc-1, argv+1);
+
+#ifdef USE_POSIX
+	setupLimits();
+	pID = fork();
+	if(pID == 0){
+		/* child */
+		pID=setsid();
 #ifdef DEBUG
-		printf("cmd[%i min]: %s\n", TIME_OUT, cmd);
+		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");
+	}else if(pID < 0){
+		fprintf(stderr, "failed to fork\n");
 		return EXIT_FAILURE;
 	}else{
-		/* parent : clean kill */
-		struct sigaction acti;
-		acti.sa_handler = &resourceLimit;
-		sigaction(SIGHUP, &acti, NULL);
-		sigaction(SIGINT, &acti, NULL);
-		sigaction(SIGQUIT, &acti, NULL);
-		sigaction(SIGABRT, &acti, NULL);	
-		sigaction(SIGTERM, &acti, NULL);
-
-		/* parent : timeout */
-		if(0!=sigaction(SIGALRM, &acti, NULL)){
-			fprintf(stderr, "failed to set timeout [%d]\n", errno);
-			resourceLimit(SIGUSR1);
-			return EXIT_FAILURE; /* never executed */
-		}
-#ifndef USE_LIMITS	
-		alarm(TIME_OUT * 60);
+		/* parent */
+		setupHandlers();
+#if !(defined(USE_POSIX_LIMITS) && defined(SIGXCPU))
+		alarm(TIME_OUT);
 #endif
 		wait(NULL);
 	}
-
 	return EXIT_SUCCESS;
-}
 #else /* USE_POSIX */
 
-#error "no implementation present for your OS"
+#error no test run implmentation present for your system
 
 #endif /* USE_POSIX else */
+}