changeset 490:d091ff903fa4

added crashRun for POSIX systems
author thomask
date Wed, 27 Apr 2005 11:54:12 +0000
parents 4cbdf8397c82
children f6a24d1475f2
files Makefile crashRun.c dstress.c
diffstat 3 files changed, 192 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Wed Apr 27 05:52:26 2005 +0000
+++ b/Makefile	Wed Apr 27 11:54:12 2005 +0000
@@ -84,6 +84,7 @@
 ifeq__		:= ./ifeq__
 extract__	:= ./extract__
 dstress__	:= ./dstress__
+crashRun__	:= ./crashRun__
 
 # settings
 to_log 		:= >> $(LOG) 2>&1
@@ -118,7 +119,10 @@
 $(extract__) : extract__.c Makefile
 	$(CC) $(CFLAGS) $< -o $@
 
-$(dstress__) : dstress.c Makefile
+$(dstress__) : dstress.c $(crashRun__) Makefile
+	$(CC) $(CFLAGS) $< -o $@
+
+$(crashRun__) : crashRun.c Makefile
 	$(CC) $(CFLAGS) $< -o $@
 
 basic_tools : $(ifeq__) $(return__) $(extract__) $(dstress__)
@@ -296,7 +300,7 @@
 #
 distclean : clean_log clean
 	$(RM) $(shell $(FIND) . -regex ".*~") $(shell $(FIND) . -regex "\\..*\\.swp") $(shell $(FIND) . -regex "#.*#")
-	$(RM) $(return__) $(ifeq__) $(extract__) $(dstress__) www/*.class
+	$(RM) $(crashRun__) $(return__) $(ifeq__) $(extract__) $(dstress__) www/*.class
 
 #
 # remove compiler and assertion messages
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crashRun.c	Wed Apr 27 11:54:12 2005 +0000
@@ -0,0 +1,101 @@
+/*
+ * crashRun - execute command with timeout limit and catch segfaults 
+ *
+ * Copyright (C) 2005 Thomas Kuehne <thomas@kuehne.cn>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * $HeadURL$
+ * $Date$
+ * $Author$
+ *
+ */
+
+#ifdef linux
+#define USE_POSIX
+#endif
+     
+#if defined(__APPLE__) && defined(__MACH__)
+#define USE_POSIX
+#endif
+
+#ifdef __FreeBSD__
+#define USE_POSIX
+#endif
+
+#ifdef USE_POSIX
+
+#include <unistd.h>
+#include <sys/wait.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* timeout in seconds */
+const int TIME_OUT=480;
+
+void onTimeOut(){
+	printf("EXIT CODE: timeout (%d sec)\n", TIME_OUT);
+	fflush(stdout);
+	fflush(stderr);
+	kill(0, SIGKILL);
+
+	exit(EXIT_FAILURE); // never called
+}
+
+int main(int argc, char** arg){
+	pid_t pID = fork();
+	if (pID == 0){
+		/* child: construct cmd */
+		int cmdLen=1;
+		int i;
+		for(i=1; i<argc; i++){
+			cmdLen+=strlen(arg[i]);
+			cmdLen+=3;
+		}
+
+		char* cmd = malloc(cmdLen);
+		*cmd='\x00';
+	
+		for(i=1; i<argc; i++){
+			strcat(cmd, "\"");
+			strcat(cmd, arg[i]);
+			strcat(cmd, "\" ");
+		}
+		printf("cmd[%i s]: %s\n", TIME_OUT, cmd);
+		printf("EXIT CODE: %i\n", system(cmd));
+	}else if (pID < 0){
+        	fprintf(stderr, "failed to fork\n");
+		return EXIT_FAILURE;
+	}else{
+      		/* parent : timeout */
+		struct sigaction acti;
+		acti.sa_handler = &onTimeOut;
+		if(0!=sigaction(SIGALRM, &acti, NULL)){
+			fprintf(stderr, "failed to set timeout\n");
+			onTimeOut();
+			return EXIT_FAILURE;
+		}	
+		alarm(TIME_OUT);
+		wait(NULL);
+	}
+
+	return EXIT_SUCCESS;
+}
+#else
+
+#error "no implementation for your OS present"
+
+#endif /* USE_POSIX else */
--- a/dstress.c	Wed Apr 27 05:52:26 2005 +0000
+++ b/dstress.c	Wed Apr 27 11:54:12 2005 +0000
@@ -34,12 +34,29 @@
 #define TAG 		"__DSTRESS_DFLAGS__"
 #define OBJ		"-odobj "
 #define TLOG		"log.tmp"
+#define CRASH_RUN	"./crashRun__"
 
 #define RUN		1
 #define NORUN		2
 #define COMPILE		4
 #define NOCOMPILE	8
 
+/* secure malloc */
+void *xmalloc(size_t size){
+	void *p;
+	if (p < 0){
+		fprintf(stderr,"Failed to allocate %zd bytes!\n", size);
+		exit(EXIT_FAILURE);
+	}
+	p = malloc(size);
+	if (p == NULL){
+		fprintf(stderr,"Failed to allocate %zd bytes!\n", size);
+		exit(EXIT_FAILURE);
+	}
+	return p;
+}
+#define malloc xmalloc
+
 #ifdef __GNU_LIBRARY__
 #define USE_POSIX
 #endif
@@ -63,15 +80,22 @@
 
 #ifdef USE_POSIX
 
-#define SHELL_RETURN_OK 0
-#define SHELL_RETURN_FAIL 256
-#define crashRun system
-
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
+
+#else
+#ifdef WIN32
+
+#include <windows.h>
+
+#endif /* WIN 32 */
+#endif /* USE_POSIX else */
+
+
 char* loadFile(char* filename){
+#ifdef USE_POSIX
 	char* back = NULL;
 	struct stat fileInfo;
 	int file = open(filename, O_RDONLY);
@@ -97,36 +121,9 @@
 
 	fprintf(stderr, "File not found \"%s\"\n", filename);
 	exit(EXIT_FAILURE);
-}
-
-void *xmalloc(size_t size)
-{
-	void *p;
-	if (p < 0)
-	{
-		fprintf(stderr,"Failed to allocate %zd bytes!\n", size);
-		exit(EXIT_FAILURE);
-	}
-	p = malloc(size);
-	if (p == NULL)
-	{
-		fprintf(stderr,"Failed to allocate %zd bytes!\n", size);
-		exit(EXIT_FAILURE);
-	}
-	return p;
-}
-
-#define malloc xmalloc
-
-#else
-
+#else 
 #ifdef WIN32
 
-#define SHELL_RETURN_OK 0
-#define SHELL_RETURN_FAIL 1
-
-#include <windows.h>
-char* loadFile(char* filename){
 	char* back=NULL;
 	DWORD size, numread;
 	HANDLE file=CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
@@ -154,17 +151,13 @@
 
 	fprintf(stderr, "File not found \"%s\"\n", filename);
 	exit(EXIT_FAILURE);
-}
-#error no crashRun adaptation available for this system
+#else
 
-#else
-#error no loadFile adaptation available for this system
-
-/* like system(char*) but has to return without human intervention even if the application segfaults */
-#error no crashRun adaptation available for this system
+#error "no loadFile implementation present"
 
 #endif /* WIN32 else */
 #endif /* USE_POSIX else */
+}
 
 /* cleanup "/" versus "\" in filenames */
 char* cleanPathSeperator(char* filename){
@@ -185,6 +178,7 @@
 	return filename;
 }
 
+
 /* Query the environment for the compiler name */
 char* getCompiler(){
 	char* back = getenv("DMD");
@@ -209,6 +203,7 @@
 	return cleanPathSeperator(back);
 }
 
+
 /* extract the FIRST occurance of a given FLAG until the next linebreak */
 char* getCaseFlag(const char* data, const char* tag){
 	char* begin;
@@ -316,7 +311,7 @@
 
 int checkRuntimeErrorMessage(const char* file_, const char* line_, const char* buffer){
 	/* PhobosLong	dir/file.d(2)
-	 * Phobos		package.module(2)
+	 * Phobos	package.module(2)
 	 */
 
 	char* file;
@@ -419,6 +414,44 @@
 	return back;
 }
 
+int hadExecCrash(const char* buffer){
+	if(strstr(buffer, "Segmentation fault")!=NULL 
+			|| strstr(buffer, "Internal error")!= NULL 
+			|| strstr(buffer, "gcc.gnu.org/bugs")!=NULL)
+	{
+		return 1;
+	}
+	return 0;
+}
+
+/* segfault resitant system call with time out */
+int crashRun(const char* cmd){
+#ifdef USE_POSIX
+	char* buffer=malloc(4+strlen(CRASH_RUN)+strlen(cmd));
+	buffer[0]='\x00';
+	strcat(buffer, "\"");
+	strcat(buffer, CRASH_RUN);
+	strcat(buffer, "\" ");
+	strcat(buffer, cmd);
+	system(buffer);
+	buffer=loadFile(TLOG);
+
+	if(strstr(buffer, "EXIT CODE: 0")){
+		return EXIT_SUCCESS;
+	}else if(strstr(buffer, "EXIT CODE: 256")
+			|| strstr(buffer, "EXIT CODE: timeout"))
+	{
+		return EXIT_FAILURE;
+	}else{
+		return RAND_MAX;
+	}
+#else
+
+#error no crashRun implementation present
+	
+#endif /* USE_POSIX else */
+}
+
 
 int main(int argc, char* arg[]){
 	char* compiler;		/* the compiler - from enviroment flag "DMD" */
@@ -526,12 +559,12 @@
 		fprintf(stderr, "%s\n", buffer);
 		good_error = checkErrorMessage(error_file, error_line, buffer);
 
-		if(strstr(buffer, "Internal error")!= NULL || strstr(buffer, "gcc.gnu.org/bugs")!=NULL){
+		if(hadExecCrash(buffer)){
 			printf("ERROR:\t%s (Internal compiler error)\n", case_file);
 		}else if(modus==COMPILE){
-			if(res==SHELL_RETURN_OK){
+			if(res==EXIT_SUCCESS){
 				printf("PASS: \t%s\n", case_file);
-			}else if(res==SHELL_RETURN_FAIL && good_error){
+			}else if(res==EXIT_FAILURE && good_error){
 				if(checkErrorMessage(case_file, "", buffer)){
 					printf("FAIL: \t%s [%d]\n", case_file, res);
 				}else{
@@ -543,13 +576,13 @@
 				printf("ERROR:\t%s [%d] [bad error message]\n", case_file, res);
 			}
 		}else{
-			if(res==SHELL_RETURN_FAIL){
+			if(res==EXIT_FAILURE){
 				if(good_error){
 					printf("XFAIL:\t%s\n", case_file);
 				}else{
 					printf("FAIL: \t%s [bad error message]\n", case_file);
 				}
-			}else if(res==SHELL_RETURN_OK){
+			}else if(res==EXIT_SUCCESS){
 				printf("XPASS:\t%s\n", case_file);
 			}else{
 				printf("ERROR:\t%s [%d]\n", case_file, res);
@@ -593,15 +626,15 @@
 		buffer = loadFile(TLOG);
 		fprintf(stderr, "%s", buffer);
 		good_error = checkErrorMessage(error_file, error_line, buffer);
-		if(strstr(buffer, "Internal error")!= NULL || strstr(buffer, "gcc.gnu.org/bugs")!=NULL){
+		if(hadExecCrash(buffer)){
 			printf("ERROR:\t%s (Internal compiler error)\n", case_file);
 			fprintf(stderr, "\n--------\n");
 			return  EXIT_SUCCESS;
-		}else if(res==SHELL_RETURN_FAIL && good_error){
+		}else if(res==EXIT_FAILURE && good_error){
 			printf("FAIL: \t%s [%d]\n", case_file, res);
 			fprintf(stderr, "\n--------\n");
 			return  EXIT_SUCCESS;
-		}else if(res!=SHELL_RETURN_OK){
+		}else if(res!=EXIT_SUCCESS){
 			if(good_error){
 				printf("ERROR:\t%s [%d]\n", case_file, res);
 			}else{
@@ -626,9 +659,9 @@
 		fprintf(stderr, "%s\n", buffer);
 		good_error = checkRuntimeErrorMessage(error_file, error_line, buffer);
 		if(modus==RUN){
-			if(res==SHELL_RETURN_OK){
+			if(res==EXIT_SUCCESS){
 				printf("PASS: \t%s\n", case_file);
-			}else if(res==SHELL_RETURN_FAIL && good_error){
+			}else if(res==EXIT_FAILURE && good_error){
 				printf("FAIL: \t%s [run: %d]\n", case_file, res);
 			}else{
 				if(good_error){
@@ -638,13 +671,13 @@
 				}
 			}
 		}else{
-			if(res==SHELL_RETURN_FAIL){
+			if(res==EXIT_FAILURE){
 				if(good_error){
 					printf("XFAIL:\t%s\n", case_file);
 				}else{
 					printf("FAIL: \t%s [bad errror message]\n", case_file);
 				}
-			}else if(res==SHELL_RETURN_OK){
+			}else if(res==EXIT_SUCCESS){
 				printf("XPASS:\t%s [norun: %d]\n", case_file, res);
 			}else{
 				printf("ERROR:\t%s [norun: %d]\n", case_file, res);