Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
authorRyan C. Gordon <icculus@icculus.org>
Wed, 28 Sep 2005 11:36:20 +0000
changeset 1151 be9c9c8f6d53
parent 1150 7d8e1925f35b
child 1152 51a8702d8ecd
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe if SDL is built with a non-cdecl calling convention, and it's just generally bad practice anyhow. Now programs explicitly call SDL_Quit() where appropriate, wrap SDL_Quit() in a cdecl function where it can't be avoided, and rely on the parachute where a crash might have hit the atexit() before (these ARE test programs, after all!).
test/checkkeys.c
test/loopwave.c
test/testalpha.c
test/testbitmap.c
test/testcdrom.c
test/testdyngl.c
test/testerror.c
test/testgamma.c
test/testhread.c
test/testlock.c
test/testoverlay.c
test/testoverlay2.c
test/testpalette.c
test/testsem.c
test/testsprite.c
test/testtimer.c
test/testwin.c
test/testwm.c
test/threadwin.c
test/torturethread.c
--- a/test/checkkeys.c	Wed Sep 28 06:38:22 2005 +0000
+++ b/test/checkkeys.c	Wed Sep 28 11:36:20 2005 +0000
@@ -10,6 +10,13 @@
 
 #include "SDL.h"
 
+/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
+static void quit(int rc)
+{
+	SDL_Quit();
+	exit(rc);
+}
+
 static void print_modifiers(void)
 {
 	int mod;
@@ -82,9 +89,8 @@
 	/* Initialize SDL */
 	if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
 		fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
-		exit(1);
+		return(1);
 	}
-	atexit(SDL_Quit);
 
 	videoflags = SDL_SWSURFACE;
 	while( argc > 1 ) {
@@ -93,7 +99,7 @@
 			videoflags |= SDL_FULLSCREEN;
 		} else {
 			fprintf(stderr, "Usage: %s [-fullscreen]\n", argv[0]);
-			exit(1);
+			quit(1);
 		}
 	}
 
@@ -101,7 +107,7 @@
 	if ( SDL_SetVideoMode(640, 480, 0, videoflags) == NULL ) {
 		fprintf(stderr, "Couldn't set 640x480 video mode: %s\n",
 							SDL_GetError());
-		exit(2);
+		quit(2);
 	}
 
 	/* Enable UNICODE translation for keyboard input */
@@ -132,5 +138,7 @@
 				break;
 		}
 	}
+
+	SDL_Quit();
 	return(0);
 }
--- a/test/loopwave.c	Wed Sep 28 06:38:22 2005 +0000
+++ b/test/loopwave.c	Wed Sep 28 11:36:20 2005 +0000
@@ -19,6 +19,15 @@
 	int      soundpos;		/* Current play position */
 } wave;
 
+
+/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
+static void quit(int rc)
+{
+	SDL_Quit();
+	exit(rc);
+}
+
+
 void fillerup(void *unused, Uint8 *stream, int len)
 {
 	Uint8 *waveptr;
@@ -54,13 +63,12 @@
 	/* Load the SDL library */
 	if ( SDL_Init(SDL_INIT_AUDIO) < 0 ) {
 		fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
-		exit(1);
+		return(1);
 	}
-	atexit(SDL_Quit);
 
 	if ( argv[1] == NULL ) {
 		fprintf(stderr, "Usage: %s <wavefile>\n", argv[0]);
-		exit(1);
+		quit(1);
 	}
 
 	/* Load the wave file into memory */
@@ -68,7 +76,7 @@
 			&wave.spec, &wave.sound, &wave.soundlen) == NULL ) {
 		fprintf(stderr, "Couldn't load %s: %s\n",
 						argv[1], SDL_GetError());
-		exit(1);
+		quit(1);
 	}
 	wave.spec.callback = fillerup;
 
@@ -86,7 +94,7 @@
 	if ( SDL_OpenAudio(&wave.spec, NULL) < 0 ) {
 		fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
 		SDL_FreeWAV(wave.sound);
-		exit(2);
+		quit(2);
 	}
 	SDL_PauseAudio(0);
 
@@ -98,5 +106,6 @@
 	/* Clean up on signal */
 	SDL_CloseAudio();
 	SDL_FreeWAV(wave.sound);
+	SDL_Quit();
 	return(0);
 }
--- a/test/testalpha.c	Wed Sep 28 06:38:22 2005 +0000
+++ b/test/testalpha.c	Wed Sep 28 11:36:20 2005 +0000
@@ -12,6 +12,14 @@
 
 #define FRAME_TICKS	(1000/30)		/* 30 frames/second */
 
+/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
+static void quit(int rc)
+{
+	SDL_Quit();
+	exit(rc);
+}
+
+
 /* Create a "light" -- a yellowish surface with variable alpha */
 SDL_Surface *CreateLight(SDL_Surface *screen, int radius)
 {
@@ -292,9 +300,8 @@
 	/* Initialize SDL */
 	if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
 		fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
-		exit(1);
+		return(1);
 	}
-	atexit(SDL_Quit);
 
 	/* Alpha blending doesn't work well at 8-bit color */
 	info = SDL_GetVideoInfo();
@@ -327,7 +334,7 @@
 			fprintf(stderr, 
 			"Usage: %s [-bpp N] [-warp] [-hw] [-fullscreen]\n",
 								argv[0]);
-			exit(1);
+			quit(1);
 		}
 	}
 
@@ -335,14 +342,14 @@
 	if ( (screen=SDL_SetVideoMode(640,480,video_bpp,videoflags)) == NULL ) {
 		fprintf(stderr, "Couldn't set 640x480x%d video mode: %s\n",
 						video_bpp, SDL_GetError());
-		exit(2);
+		quit(2);
 	}
 
 	/* Set the surface pixels and refresh! */
 	if ( SDL_LockSurface(screen) < 0 ) {
 		fprintf(stderr, "Couldn't lock the display surface: %s\n",
 							SDL_GetError());
-		exit(2);
+		quit(2);
 	}
 	buffer=(Uint8 *)screen->pixels;
 	if (screen->format->BytesPerPixel!=2) {
@@ -371,13 +378,13 @@
 	/* Create the light */
 	light = CreateLight(screen, 82);
 	if ( light == NULL ) {
-		exit(1);
+		quit(1);
 	}
 
 	/* Load the sprite */
 	if ( LoadSprite(screen, "icon.bmp") < 0 ) {
 		SDL_FreeSurface(light);
-		exit(1);
+		quit(1);
 	}
 
 	/* Print out information about our surfaces */
@@ -492,5 +499,7 @@
 		printf("%d alpha blits, ~%4.4f ms per blit\n", 
 			flashes, (float)flashtime/flashes);
 	}
+
+	SDL_Quit();
 	return(0);
 }
--- a/test/testbitmap.c	Wed Sep 28 06:38:22 2005 +0000
+++ b/test/testbitmap.c	Wed Sep 28 11:36:20 2005 +0000
@@ -8,6 +8,13 @@
 #include "SDL.h"
 #include "picture.xbm"
 
+/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
+static void quit(int rc)
+{
+	SDL_Quit();
+	exit(rc);
+}
+
 SDL_Surface *LoadXBM(SDL_Surface *screen, int w, int h, Uint8 *bits)
 {
 	SDL_Surface *bitmap;
@@ -61,9 +68,8 @@
 	/* Initialize SDL */
 	if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
 		fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
-		exit(1);
+		return(1);
 	}
-	atexit(SDL_Quit);
 
 	video_bpp = 0;
 	videoflags = SDL_SWSURFACE;
@@ -85,7 +91,7 @@
 			fprintf(stderr,
 			"Usage: %s [-bpp N] [-warp] [-hw] [-fullscreen]\n",
 								argv[0]);
-			exit(1);
+			quit(1);
 		}
 	}
 
@@ -93,7 +99,7 @@
 	if ( (screen=SDL_SetVideoMode(640,480,video_bpp,videoflags)) == NULL ) {
 		fprintf(stderr, "Couldn't set 640x480x%d video mode: %s\n",
 						video_bpp, SDL_GetError());
-		exit(2);
+		quit(2);
 	}
 
 	if (video_bpp==8) {
@@ -110,7 +116,7 @@
 	if ( SDL_LockSurface(screen) < 0 ) {
 		fprintf(stderr, "Couldn't lock the display surface: %s\n",
 							SDL_GetError());
-		exit(2);
+		quit(2);
 	}
 	buffer=(Uint8 *)screen->pixels;
 	if (screen->format->BytesPerPixel!=2) {
@@ -139,7 +145,7 @@
 	bitmap = LoadXBM(screen, picture_width, picture_height,
 					(Uint8 *)picture_bits);
 	if ( bitmap == NULL ) {
-		exit(1);
+		quit(1);
 	}
 
 	/* Wait for a keystroke */
@@ -173,5 +179,6 @@
 		}
 	}
 	SDL_FreeSurface(bitmap);
+	SDL_Quit();
 	return(0);
 }
--- a/test/testcdrom.c	Wed Sep 28 06:38:22 2005 +0000
+++ b/test/testcdrom.c	Wed Sep 28 11:36:20 2005 +0000
@@ -7,6 +7,12 @@
 
 #include "SDL.h"
 
+/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
+static void quit(int rc)
+{
+	SDL_Quit();
+	exit(rc);
+}
 
 static void PrintStatus(int driveindex, SDL_CD *cdrom)
 {
@@ -92,14 +98,13 @@
 	/* Initialize SDL first */
 	if ( SDL_Init(SDL_INIT_CDROM) < 0 ) {
 		fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
-		exit(1);
+		return(1);
 	}
-	atexit(SDL_Quit);
 
 	/* Find out how many CD-ROM drives are connected to the system */
 	if ( SDL_CDNumDrives() == 0 ) {
 		printf("No CD-ROM devices detected\n");
-		exit(0);
+		quit(0);
 	}
 	printf("Drives available: %d\n", SDL_CDNumDrives());
 	for ( i=0; i<SDL_CDNumDrives(); ++i ) {
@@ -116,7 +121,7 @@
 	if ( cdrom == NULL ) {
 		fprintf(stderr, "Couldn't open drive %d: %s\n", drive,
 							SDL_GetError());
-		exit(2);
+		quit(2);
 	}
 #ifdef TEST_NULLCD
 	cdrom = NULL;
@@ -192,11 +197,12 @@
 		} else {
 			PrintUsage(argv[0]);
 			SDL_CDClose(cdrom);
-			exit(1);
+			quit(1);
 		}
 	}
 	PrintStatus(drive, cdrom);
 	SDL_CDClose(cdrom);
+	SDL_Quit();
 
 	return(0);
 }
--- a/test/testdyngl.c	Wed Sep 28 06:38:22 2005 +0000
+++ b/test/testdyngl.c	Wed Sep 28 11:36:20 2005 +0000
@@ -23,6 +23,13 @@
 
 #include "SDL_opengl.h"
 
+/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
+static void quit(int rc)
+{
+	SDL_Quit();
+	exit(rc);
+}
+
 void* get_funcaddr(const char* p)
 {
 	void* f=SDL_GL_GetProcAddress(p);
@@ -33,7 +40,7 @@
 	else
 	{
 		printf("Unable to get function pointer for %s\n",p);
-		exit(1);
+		quit(1);
 	}
 }
 
@@ -104,27 +111,25 @@
 	if (SDL_Init(SDL_INIT_VIDEO)<0)
 	{
 		printf("Unable to init SDL : %s\n",SDL_GetError());
-		exit(1);
+		return(1);
 	}
 
-	atexit(SDL_Quit);
-	
 	if (SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1)<0)
 	{
 		printf("Unable to set GL attribute : %s\n",SDL_GetError());
-		exit(1);
+		quit(1);
 	}
 	
 	if (SDL_GL_LoadLibrary(gl_library)<0)
 	{
 		printf("Unable to dynamically open GL lib : %s\n",SDL_GetError());
-		exit(1);
+		quit(1);
 	}
 
 	if (SDL_SetVideoMode(640,480,0,SDL_OPENGL)==NULL)
 	{
 		printf("Unable to open video mode : %s\n",SDL_GetError());
-		exit(1);
+		quit(1);
 	}
 
 	/* Set the window manager title bar */
--- a/test/testerror.c	Wed Sep 28 06:38:22 2005 +0000
+++ b/test/testerror.c	Wed Sep 28 11:36:20 2005 +0000
@@ -10,6 +10,13 @@
 
 static int alive = 0;
 
+/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
+static void quit(int rc)
+{
+	SDL_Quit();
+	exit(rc);
+}
+
 int ThreadFunc(void *data)
 {
 	/* Set the child thread error string */
@@ -30,9 +37,8 @@
 	/* Load the SDL library */
 	if ( SDL_Init(0) < 0 ) {
 		fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
-		exit(1);
+		return(1);
 	}
-	atexit(SDL_Quit);
 
 	/* Set the error value for the main thread */
 	SDL_SetError("No worries");
@@ -41,7 +47,7 @@
 	thread = SDL_CreateThread(ThreadFunc, "#1");
 	if ( thread == NULL ) {
 		fprintf(stderr, "Couldn't create thread: %s\n", SDL_GetError());
-		exit(1);
+		quit(1);
 	}
 	SDL_Delay(5*1000);
 	printf("Waiting for thread #1\n");
@@ -50,5 +56,6 @@
 
 	printf("Main thread error string: %s\n", SDL_GetError());
 
+	SDL_Quit();
 	return(0);
 }
--- a/test/testgamma.c	Wed Sep 28 06:38:22 2005 +0000
+++ b/test/testgamma.c	Wed Sep 28 11:36:20 2005 +0000
@@ -8,6 +8,13 @@
 
 #include "SDL.h"
 
+/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
+static void quit(int rc)
+{
+	SDL_Quit();
+	exit(rc);
+}
+
 /* Turn a normal gamma value into an appropriate gamma ramp */
 void CalculateGamma(double gamma, Uint16 *ramp)
 {
@@ -82,16 +89,15 @@
 	if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
 		fprintf(stderr,
 			"Couldn't initialize SDL: %s\n", SDL_GetError());
-		exit(1);
+		return(1);
 	}
-	atexit(SDL_Quit);
 
 	/* Initialize the display, always use hardware palette */
 	screen = SDL_SetVideoMode(w, h, bpp, flags | SDL_HWPALETTE);
 	if ( screen == NULL ) {
 		fprintf(stderr, "Couldn't set %dx%d video mode: %s\n",
 						w, h, SDL_GetError());
-		exit(1);
+		quit(1);
 	}
 
 	/* Set the window manager title bar */
@@ -104,7 +110,7 @@
 	}
 	if ( SDL_SetGamma(gamma, gamma, gamma) < 0 ) {
 		fprintf(stderr, "Unable to set gamma: %s\n", SDL_GetError());
-		exit(1);
+		quit(1);
 	}
 
 #if 0 /* This isn't supported.  Integrating the gamma ramps isn't exact */
@@ -186,5 +192,6 @@
 	}
 	SDL_Delay(1*1000);
 
+	SDL_Quit();
 	return(0);
 }
--- a/test/testhread.c	Wed Sep 28 06:38:22 2005 +0000
+++ b/test/testhread.c	Wed Sep 28 11:36:20 2005 +0000
@@ -10,6 +10,13 @@
 
 static int alive = 0;
 
+/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
+static void quit(int rc)
+{
+	SDL_Quit();
+	exit(rc);
+}
+
 int ThreadFunc(void *data)
 {
 	printf("Started thread %s: My thread id is %u\n",
@@ -27,7 +34,7 @@
 	printf("Killed with SIGTERM, waiting 5 seconds to exit\n");
 	SDL_Delay(5*1000);
 	alive = 0;
-	exit(0);
+	quit(0);
 }
 
 int main(int argc, char *argv[])
@@ -37,15 +44,14 @@
 	/* Load the SDL library */
 	if ( SDL_Init(0) < 0 ) {
 		fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
-		exit(1);
+		return(1);
 	}
-	atexit(SDL_Quit);
 
 	alive = 1;
 	thread = SDL_CreateThread(ThreadFunc, "#1");
 	if ( thread == NULL ) {
 		fprintf(stderr, "Couldn't create thread: %s\n", SDL_GetError());
-		exit(1);
+		quit(1);
 	}
 	SDL_Delay(5*1000);
 	printf("Waiting for thread #1\n");
@@ -56,7 +62,7 @@
 	thread = SDL_CreateThread(ThreadFunc, "#2");
 	if ( thread == NULL ) {
 		fprintf(stderr, "Couldn't create thread: %s\n", SDL_GetError());
-		exit(1);
+		quit(1);
 	}
 	SDL_Delay(5*1000);
 	printf("Killing thread #2\n");
@@ -67,9 +73,10 @@
 	thread = SDL_CreateThread(ThreadFunc, "#3");
 	if ( thread == NULL ) {
 		fprintf(stderr, "Couldn't create thread: %s\n", SDL_GetError());
-		exit(1);
+		quit(1);
 	}
 	raise(SIGTERM);
 
+	SDL_Quit();	/* Never reached */
 	return(0);	/* Never reached */
 }
--- a/test/testlock.c	Wed Sep 28 06:38:22 2005 +0000
+++ b/test/testlock.c	Wed Sep 28 11:36:20 2005 +0000
@@ -15,6 +15,15 @@
 static Uint32 mainthread;
 static SDL_Thread *threads[6];
 
+/*
+ * SDL_Quit() shouldn't be used with atexit() directly because
+ *  calling conventions may differ...
+ */
+static void SDL_Quit_Wrapper(void)
+{
+	SDL_Quit();
+}
+
 void printid(void)
 {
 	printf("Process %u:  exiting\n", SDL_ThreadID());
@@ -68,7 +77,7 @@
 		fprintf(stderr, "%s\n", SDL_GetError());
 		exit(1);
 	}
-	atexit(SDL_Quit);
+	atexit(SDL_Quit_Wrapper);
 
 	if ( (mutex=SDL_CreateMutex()) == NULL ) {
 		fprintf(stderr, "Couldn't create mutex: %s\n", SDL_GetError());
--- a/test/testoverlay.c	Wed Sep 28 06:38:22 2005 +0000
+++ b/test/testoverlay.c	Wed Sep 28 11:36:20 2005 +0000
@@ -21,6 +21,13 @@
 int luminance;
 int w, h;
 
+/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
+static void quit(int rc)
+{
+	SDL_Quit();
+	exit(rc);
+}
+
 /* NOTE: These RGB conversion functions are not intended for speed,
          only as examples.
 */
@@ -347,7 +354,7 @@
 			} else {
 				fprintf(stderr,
 				"The -delay option requires an argument\n");
-				exit(1);
+				return(1);
 			}
 		} else
 		if ( strcmp(argv[1], "-width") == 0 ) {
@@ -357,7 +364,7 @@
 			} else {
 				fprintf(stderr,
 				"The -width option requires an argument\n");
-				exit(1);
+				return(1);
 			}
 		} else
 		if ( strcmp(argv[1], "-height") == 0 ) {
@@ -367,7 +374,7 @@
 			} else {
 				fprintf(stderr,
 				"The -height option requires an argument\n");
-				exit(1);
+				return(1);
 			}
 		} else
 		if ( strcmp(argv[1], "-bpp") == 0 ) {
@@ -378,7 +385,7 @@
 			} else {
 				fprintf(stderr,
 				"The -bpp option requires an argument\n");
-				exit(1);
+				return(1);
 			}
 		} else
 		if ( strcmp(argv[1], "-lum") == 0 ) {
@@ -389,7 +396,7 @@
 			} else {
 				fprintf(stderr,
 				"The -lum option requires an argument\n");
-				exit(1);
+				return(1);
 			}
 		} else
 		if ( strcmp(argv[1], "-format") == 0 ) {
@@ -407,14 +414,14 @@
 				else
 				{
 					fprintf(stderr, "The -format option %s is not recognized\n",argv[2]);
-					exit(1);
+					return(1);
 				}
 				argv += 2;
 				argc -= 2;
 			} else {
 				fprintf(stderr,
 				"The -format option requires an argument\n");
-				exit(1);
+				return(1);
 			}
 		} else
 		if ( strcmp(argv[1], "-hw") == 0 ) {
@@ -439,7 +446,7 @@
 		} else
 		if (( strcmp(argv[1], "-help") == 0 ) || (strcmp(argv[1], "-h") == 0)) {
                         PrintUsage(argv0);
-                        exit(1);
+                        return(1);
 		} else
 		if ( strcmp(argv[1], "-fullscreen") == 0 ) {
 			video_flags |= SDL_FULLSCREEN;
@@ -451,16 +458,15 @@
 	if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
 		fprintf(stderr,
 			"Couldn't initialize SDL: %s\n", SDL_GetError());
-		exit(1);
+		return(1);
 	}
-	atexit(SDL_Quit);			/* Clean up on exit */
 
 	/* Initialize the display */
 	screen = SDL_SetVideoMode(w, h, desired_bpp, video_flags);
 	if ( screen == NULL ) {
 		fprintf(stderr, "Couldn't set %dx%dx%d video mode: %s\n",
 					w, h, desired_bpp, SDL_GetError());
-		exit(1);
+		quit(1);
 	}
 	printf("Set%s %dx%dx%d mode\n",
 			screen->flags & SDL_FULLSCREEN ? " fullscreen" : "",
@@ -481,7 +487,7 @@
 	if ( pic == NULL ) {
 		fprintf(stderr, "Couldn't load %s: %s\n", bmpfile,
 							SDL_GetError());
-		exit(1);
+		quit(1);
 	}
 
 	/* Convert the picture to 32bits, for easy conversion */
@@ -518,7 +524,7 @@
 		{
 			fprintf(stderr, "Couldn't convert picture to 32bits RGB: %s\n",
 							SDL_GetError());
-			exit(1);
+			quit(1);
 		}
 		SDL_FreeSurface(pic);
 		pic=newsurf;
@@ -528,7 +534,7 @@
 	overlay = SDL_CreateYUVOverlay(pic->w, pic->h, overlay_format, screen);
 	if ( overlay == NULL ) {
 		fprintf(stderr, "Couldn't create overlay: %s\n", SDL_GetError());
-		exit(1);
+		quit(1);
 	}
 	printf("Created %dx%dx%d %s %s overlay\n",overlay->w,overlay->h,overlay->planes,
 			overlay->hw_overlay?"hardware":"software",
@@ -566,7 +572,7 @@
 			break;
 		default:
 			printf("cannot convert RGB picture to obtained YUV format!\n");
-			exit(1);
+			quit(1);
 			break;
 	}
 #ifdef BENCHMARK_SDL
@@ -584,6 +590,7 @@
 	printf("Time: %d milliseconds\n", now-then);
 #endif
 	SDL_Delay(delay*1000);
+	SDL_Quit();
 	return(0);
 }
 
--- a/test/testoverlay2.c	Wed Sep 28 06:38:22 2005 +0000
+++ b/test/testoverlay2.c	Wed Sep 28 11:36:20 2005 +0000
@@ -41,6 +41,14 @@
     {222, 222, 222}, {231, 198, 165}, {231, 231, 231}, {239, 206, 173}
 };
 
+
+/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
+static void quit(int rc)
+{
+	SDL_Quit();
+	exit(rc);
+}
+
 /* All RGB2YUV conversion code and some other parts of code has been taken from testoverlay.c */
 
 /* NOTE: These RGB conversion functions are not intended for speed,
@@ -288,6 +296,12 @@
     int overlay_format=SDL_YUY2_OVERLAY;
     int scale=5;
 
+    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0)
+    {
+        fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
+        return 3;
+    }
+
     while ( argc > 1 )
     {
         if (strcmp(argv[1], "-fps")== 0)
@@ -298,12 +312,12 @@
                 if (fps==0)
                 {
                     fprintf(stderr, "The -fps option requires an argument [from 1 to 1000], default is 12.\n");
-                    return -1;
+                    quit(10);
                 }
                 if ((fps<0) || (fps>1000))
                 {
                     fprintf(stderr, "The -fps option must be in range from 1 to 1000, default is 12.\n");
-                    return -1;
+                    quit(10);
                 }
                 argv += 2;
                 argc -= 2;
@@ -311,7 +325,7 @@
             else
             {
                 fprintf(stderr, "The -fps option requires an argument [from 1 to 1000], default is 12.\n");
-                return -1;
+                quit(10);
             }
         } else
         if (strcmp(argv[1], "-format") == 0)
@@ -331,7 +345,7 @@
                 else
                 {
                     fprintf(stderr, "The -format option %s is not recognized, see help for info.\n", argv[2]);
-                    return -1;
+                    quit(10);
                 }
                 argv += 2;
                 argc -= 2;
@@ -339,7 +353,7 @@
             else
             {
                 fprintf(stderr, "The -format option requires an argument, default is YUY2.\n");
-                return -1;
+                quit(10);
             }
         } else
         if (strcmp(argv[1], "-scale") == 0)
@@ -350,12 +364,12 @@
                 if (scale==0)
                 {
                     fprintf(stderr, "The -scale option requires an argument [from 1 to 50], default is 5.\n");
-                    return -1;
+                    quit(10);
                 }
                 if ((scale<0) || (scale>50))
                 {
                     fprintf(stderr, "The -scale option must be in range from 1 to 50, default is 5.\n");
-                    return -1;
+                    quit(10);
                 }
                 argv += 2;
                 argc -= 2;
@@ -363,17 +377,17 @@
             else
             {
                 fprintf(stderr, "The -fps option requires an argument [from 1 to 1000], default is 12.\n");
-                return -1;
+                quit(10);
             }
         } else
         if ((strcmp(argv[1], "-help") == 0 ) || (strcmp(argv[1], "-h") == 0))
         {
             PrintUsage(argv[0]);
-            return 0;
+            quit(0);
         } else
         {
             fprintf(stderr, "Unrecognized option: %s.\n", argv[1]);
-            return -1;
+            quit(10);
         }
         break;
     }
@@ -383,7 +397,7 @@
     {
         fprintf(stderr, "Can't allocate memory for movie !\n");
         free(RawMooseData);
-        return 1;
+        quit(1);
     }
 
     /* load the trojan moose images */
@@ -392,27 +406,19 @@
     {
         fprintf(stderr, "Can't find the file moose.dat !\n");
         free(RawMooseData);
-        return 2;
+        quit(2);
     }
    
     SDL_RWread(handle, RawMooseData, MOOSEFRAME_SIZE, MOOSEFRAMES_COUNT);
 
     SDL_RWclose(handle);
 
-    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0)
-    {
-        fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
-        free(RawMooseData);
-        return 3;
-    }
-    atexit(SDL_Quit);
-
     /* Set video mode */
     if ( (screen=SDL_SetVideoMode(MOOSEPIC_W*scale, MOOSEPIC_H*scale, 0, SDL_RESIZABLE | SDL_SWSURFACE)) == NULL )
     {
         fprintf(stderr, "Couldn't set video mode: %s\n", 0, SDL_GetError());
         free(RawMooseData);
-        return 4;
+        quit(4);
     }
 
     /* Set the window manager title bar */
@@ -426,7 +432,7 @@
         {
             fprintf(stderr, "Couldn't create SDL_Surfaces:%s\n", 0, SDL_GetError());
             free(RawMooseData);
-            return 5;
+            quit(5);
         }
         SDL_SetColors(MooseFrame[i], MooseColors, 0, 84);
 
@@ -462,7 +468,7 @@
 		if(!newsurf)
 		{
                     fprintf(stderr, "Couldn't convert picture to 32bits RGB: %s\n", SDL_GetError());
-                    return 6;
+                    quit(6);
 		}
 		SDL_FreeSurface(MooseFrame[i]);
 		MooseFrame[i]=newsurf;
@@ -475,7 +481,7 @@
     if (!overlay)
     {
         fprintf(stderr, "Couldn't create overlay: %s\n", SDL_GetError());
-        return 7;
+        quit(7);
     }
 
     printf("Created %dx%dx%d %s %s overlay\n",overlay->w,overlay->h,overlay->planes,
@@ -538,7 +544,7 @@
                      {
                          SDL_FreeSurface(MooseFrame[i]);
                      }
-                     return 0;
+                     quit(0);
             }
         }
 
@@ -586,6 +592,7 @@
         SDL_Delay(1);
     }
 
+	SDL_Quit();
     return 0;
 }
 
--- a/test/testpalette.c	Wed Sep 28 06:38:22 2005 +0000
+++ b/test/testpalette.c	Wed Sep 28 11:36:20 2005 +0000
@@ -54,10 +54,17 @@
     {0,39,172}, {0,28,152}, {0,17,132}, {0,7,114}
 };
 
+/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
+static void quit(int rc)
+{
+	SDL_Quit();
+	exit(rc);
+}
+
 static void sdlerr(char *when)
 {
     fprintf(stderr, "SDL error: %s: %s\n", when, SDL_GetError());
-    exit(1);
+    quit(1);
 }
 
 /* create a background surface */
@@ -139,8 +146,6 @@
     if(SDL_Init(SDL_INIT_VIDEO) < 0)
 	sdlerr("initialising SDL");
 
-    atexit(SDL_Quit);
-
     while(--argc) {
 	++argv;
 	if(strcmp(*argv, "-hw") == 0)
@@ -157,7 +162,7 @@
 	    fprintf(stderr,
 		    "usage: testpalette "
 		    " [-hw] [-fullscreen] [-nofade] [-gamma] [-gammaramp]\n");
-	    return 1;
+	    quit(1);
 	}
     }
 
@@ -165,7 +170,7 @@
     if(!(screen = SDL_SetVideoMode(SCRW, SCRH, 8, vidflags | SDL_HWPALETTE))) {
 	fprintf(stderr, "error setting %dx%d 8bpp indexed mode: %s\n",
 		SCRW, SCRH, SDL_GetError());
-	return 1;
+	quit(1);
     }
 
     if(!(boat[0] = SDL_LoadBMP("sail.bmp")))
@@ -327,6 +332,8 @@
 
     printf("%d frames, %.2f fps\n",
 	   frames, 1000.0 * frames / (SDL_GetTicks() - start));
+
+    SDL_Quit();
     return 0;
 }
 
--- a/test/testsem.c	Wed Sep 28 06:38:22 2005 +0000
+++ b/test/testsem.c	Wed Sep 28 11:36:20 2005 +0000
@@ -13,6 +13,13 @@
 static SDL_sem *sem;
 int alive = 1;
 
+/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
+static void quit(int rc)
+{
+	SDL_Quit();
+	exit(rc);
+}
+
 int ThreadFunc(void *data)
 {
 	while ( alive ) {
@@ -39,15 +46,14 @@
 
 	if(argc < 2) {
 		fprintf(stderr,"Usage: %s init_value\n", argv[0]);
-		exit(1);
+		return(1);
 	}
 
 	/* Load the SDL library */
 	if ( SDL_Init(0) < 0 ) {
 		fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
-		exit(1);
+		return(1);
 	}
-	atexit(SDL_Quit);
 	signal(SIGTERM, killed);
 	signal(SIGINT, killed);
 	
@@ -72,5 +78,6 @@
 	printf("Finished waiting for threads\n");
 
 	SDL_DestroySemaphore(sem);
+	SDL_Quit();
 	return(0);
 }
--- a/test/testsprite.c	Wed Sep 28 06:38:22 2005 +0000
+++ b/test/testsprite.c	Wed Sep 28 11:36:20 2005 +0000
@@ -22,6 +22,13 @@
 int sprites_visible;
 Uint16 sprite_w, sprite_h;
 
+/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
+static void quit(int rc)
+{
+	SDL_Quit();
+	exit(rc);
+}
+
 int LoadSprite(SDL_Surface *screen, char *file)
 {
 	SDL_Surface *temp;
@@ -159,9 +166,8 @@
 	/* Initialize SDL */
 	if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
 		fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
-		exit(1);
+		return(1);
 	}
-	atexit(SDL_Quit);
 
 	numsprites = NUM_SPRITES;
 	videoflags = SDL_SWSURFACE|SDL_ANYFORMAT;
@@ -201,7 +207,7 @@
 			fprintf(stderr, 
 	"Usage: %s [-bpp N] [-hw] [-flip] [-fast] [-fullscreen] [numsprites]\n",
 								argv[0]);
-			exit(1);
+			quit(1);
 		}
 	}
 
@@ -210,12 +216,12 @@
 	if ( ! screen ) {
 		fprintf(stderr, "Couldn't set %dx%d video mode: %s\n",
 					width, height, SDL_GetError());
-		exit(2);
+		quit(2);
 	}
 
 	/* Load the sprite */
 	if ( LoadSprite(screen, "icon.bmp") < 0 ) {
-		exit(1);
+		quit(1);
 	}
 
 	/* Allocate memory for the sprite info */
@@ -223,7 +229,7 @@
 	if ( mem == NULL ) {
 		SDL_FreeSurface(sprite);
 		fprintf(stderr, "Out of memory!\n");
-		exit(2);
+		quit(2);
 	}
 	sprite_rects = (SDL_Rect *)mem;
 	positions = sprite_rects;
--- a/test/testtimer.c	Wed Sep 28 06:38:22 2005 +0000
+++ b/test/testtimer.c	Wed Sep 28 11:36:20 2005 +0000
@@ -12,6 +12,13 @@
 
 static int ticks = 0;
 
+/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
+static void quit(int rc)
+{
+	SDL_Quit();
+	exit(rc);
+}
+
 static Uint32 ticktock(Uint32 interval)
 {
 	++ticks;
@@ -31,9 +38,8 @@
 
 	if ( SDL_Init(SDL_INIT_TIMER) < 0 ) {
 		fprintf(stderr, "Couldn't load SDL: %s\n", SDL_GetError());
-		exit(1);
+		return(1);
 	}
-	atexit(SDL_Quit);
 
 	/* Start the timer */
 	desired = 0;
@@ -83,5 +89,6 @@
 	SDL_RemoveTimer(t2);
 	SDL_RemoveTimer(t3);
 
+	SDL_Quit();
 	return(0);
 }
--- a/test/testwin.c	Wed Sep 28 06:38:22 2005 +0000
+++ b/test/testwin.c	Wed Sep 28 11:36:20 2005 +0000
@@ -11,6 +11,13 @@
 
 #include "SDL.h"
 
+/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
+static void quit(int rc)
+{
+	SDL_Quit();
+	exit(rc);
+}
+
 void DrawPict(SDL_Surface *screen, char *bmpfile,
 					int speedy, int flip, int nofade)
 {
@@ -245,6 +252,13 @@
 	h = 480;
 	desired_bpp = 0;
 	video_flags = 0;
+
+	if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
+		fprintf(stderr,
+			"Couldn't initialize SDL: %s\n", SDL_GetError());
+		return(1);
+	}
+
 	while ( argc > 1 ) {
 		if ( strcmp(argv[1], "-speedy") == 0 ) {
 			speedy = 1;
@@ -264,7 +278,7 @@
 			} else {
 				fprintf(stderr,
 				"The -delay option requires an argument\n");
-				exit(1);
+				quit(1);
 			}
 		} else
 		if ( strcmp(argv[1], "-width") == 0 ) {
@@ -274,7 +288,7 @@
 			} else {
 				fprintf(stderr,
 				"The -width option requires an argument\n");
-				exit(1);
+				quit(1);
 			}
 		} else
 		if ( strcmp(argv[1], "-height") == 0 ) {
@@ -284,7 +298,7 @@
 			} else {
 				fprintf(stderr,
 				"The -height option requires an argument\n");
-				exit(1);
+				quit(1);
 			}
 		} else
 		if ( strcmp(argv[1], "-bpp") == 0 ) {
@@ -295,7 +309,7 @@
 			} else {
 				fprintf(stderr,
 				"The -bpp option requires an argument\n");
-				exit(1);
+				quit(1);
 			}
 		} else
 		if ( strcmp(argv[1], "-warp") == 0 ) {
@@ -321,19 +335,12 @@
 			break;
 	}
 
-	if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
-		fprintf(stderr,
-			"Couldn't initialize SDL: %s\n", SDL_GetError());
-		exit(1);
-	}
-	atexit(SDL_Quit);			/* Clean up on exit */
-
 	/* Initialize the display */
 	screen = SDL_SetVideoMode(w, h, desired_bpp, video_flags);
 	if ( screen == NULL ) {
 		fprintf(stderr, "Couldn't set %dx%dx%d video mode: %s\n",
 					w, h, desired_bpp, SDL_GetError());
-		exit(1);
+		quit(1);
 	}
 	printf("Set%s %dx%dx%d mode\n",
 			screen->flags & SDL_FULLSCREEN ? " fullscreen" : "",
@@ -358,5 +365,6 @@
 	DrawPict(screen, argv[1], speedy, flip, nofade);
 #endif
 	SDL_Delay(delay*1000);
+	SDL_Quit();
 	return(0);
 }
--- a/test/testwm.c	Wed Sep 28 06:38:22 2005 +0000
+++ b/test/testwm.c	Wed Sep 28 11:36:20 2005 +0000
@@ -13,6 +13,13 @@
 static Uint8  video_bpp;
 static Uint32 video_flags;
 
+/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
+static void quit(int rc)
+{
+	SDL_Quit();
+	exit(rc);
+}
+
 int SetVideoMode(int w, int h)
 {
 	SDL_Surface *screen;
@@ -264,9 +271,8 @@
 	if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
 		fprintf(stderr,
 			"Couldn't initialize SDL: %s\n", SDL_GetError());
-		exit(1);
+		return(1);
 	}
-	atexit(SDL_Quit);
 
 	/* Check command line arguments */
 	w = 640;
@@ -333,7 +339,7 @@
 
 	/* Initialize the display */
 	if ( SetVideoMode(w, h) < 0 ) {
-		return(1);
+		quit(1);
 	}
 
 	/* Set an event filter that discards everything but QUIT */
@@ -355,7 +361,7 @@
 				/* Fall through to the quit handler */
 			case SDL_QUIT:
 				printf("Bye bye..\n");
-				return(0);
+				quit(0);
 			default:
 				/* This should never happen */
 				printf("Warning: Event %d wasn't filtered\n",
@@ -364,5 +370,6 @@
 		}
 	}
 	printf("SDL_WaitEvent() error: %s\n", SDL_GetError());
+	SDL_Quit();
 	return(255);
 }
--- a/test/threadwin.c	Wed Sep 28 06:38:22 2005 +0000
+++ b/test/threadwin.c	Wed Sep 28 11:36:20 2005 +0000
@@ -14,6 +14,13 @@
 /* Is the cursor visible? */
 static int visible = 1;
 
+/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
+static void quit(int rc)
+{
+	SDL_Quit();
+	exit(rc);
+}
+
 SDL_Surface *LoadIconSurface(char *file, Uint8 **maskp)
 {
 	SDL_Surface *icon;
@@ -260,9 +267,8 @@
 	if ( SDL_Init(init_flags) < 0 ) {
 		fprintf(stderr,
 			"Couldn't initialize SDL: %s\n", SDL_GetError());
-		exit(1);
+		return(1);
 	}
-	atexit(SDL_Quit);
 
 	/* Set the icon -- this must be done before the first mode set */
 	icon = LoadIconSurface("icon.bmp", &icon_mask);
@@ -277,7 +283,7 @@
 	if (  screen == NULL ) {
 		fprintf(stderr, "Couldn't set 640x480x%d video mode: %s\n",
 						video_bpp, SDL_GetError());
-		exit(1);
+		quit(1);
 	}
 	printf("Running in %s mode\n", screen->flags & SDL_FULLSCREEN ?
 						"fullscreen" : "windowed");
@@ -302,7 +308,7 @@
 	if ( SDL_LockSurface(screen) < 0 ) {
 		fprintf(stderr, "Couldn't lock display surface: %s\n",
 							SDL_GetError());
-		exit(2);
+		quit(2);
 	}
 	buffer = (Uint8 *)screen->pixels;
 	for ( i=0; i<screen->h; ++i ) {
@@ -326,5 +332,6 @@
 	}
 	SDL_WaitThread(mouse_thread, NULL);
 	SDL_WaitThread(keybd_thread, NULL);
+	SDL_Quit();
 	return(0);
 }
--- a/test/torturethread.c	Wed Sep 28 06:38:22 2005 +0000
+++ b/test/torturethread.c	Wed Sep 28 11:36:20 2005 +0000
@@ -13,6 +13,13 @@
 
 static char volatile time_for_threads_to_die[NUMTHREADS];
 
+/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
+static void quit(int rc)
+{
+	SDL_Quit();
+	exit(rc);
+}
+
 int SubThreadFunc(void *data) {
 	while(! *(int volatile *)data) {
 		; /*SDL_Delay(10); /* do nothing */
@@ -57,10 +64,8 @@
 	/* Load the SDL library */
 	if ( SDL_Init(0) < 0 ) {
 		fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
-		exit(1);
+		return(1);
 	}
-	atexit(SDL_Quit);
-
 
 	signal(SIGSEGV, SIG_DFL);
 	for(i = 0; i < NUMTHREADS; i++) {
@@ -70,7 +75,7 @@
 		if ( threads[i] == NULL ) {
 			fprintf(stderr,
 			"Couldn't create thread: %s\n", SDL_GetError());
-			exit(1);
+			quit(1);
 		}
 	}
 
@@ -81,5 +86,6 @@
 	for(i = NUMTHREADS-1; i >= 0; --i) {
 		SDL_WaitThread(threads[i], NULL);
 	}
-	return(0);	/* Never reached */
+	SDL_Quit();
+	return(0);
 }