src/SDL_fatal.c
author Ryan C. Gordon <icculus@icculus.org>
Thu, 29 Sep 2005 09:43:00 +0000
changeset 1152 51a8702d8ecd
parent 861 863da1c38c7e
child 1312 c9b51268668f
permissions -rw-r--r--
Updates to PocketPC (WinCE) support, thanks to Dmitry Yakimov at
activekitten.com.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2004 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Library General Public
     7     License as published by the Free Software Foundation; either
     8     version 2 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Library General Public License for more details.
    14 
    15     You should have received a copy of the GNU Library General Public
    16     License along with this library; if not, write to the Free
    17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 
    23 #ifdef SAVE_RCSID
    24 static char rcsid =
    25  "@(#) $Id$";
    26 #endif
    27 
    28 #ifdef _WIN32_WCE
    29 #define NO_SIGNAL_H
    30 #endif
    31  
    32 /* General fatal signal handling code for SDL */
    33 
    34 #ifdef NO_SIGNAL_H
    35 
    36 /* No signals on this platform, nothing to do.. */
    37 
    38 void SDL_InstallParachute(void)
    39 {
    40 	return;
    41 }
    42 
    43 void SDL_UninstallParachute(void)
    44 {
    45 	return;
    46 }
    47 
    48 #else
    49 
    50 #include <stdlib.h>
    51 #include <stdio.h>
    52 #include <signal.h>
    53 #include <string.h>
    54 
    55 #include "SDL.h"
    56 #include "SDL_fatal.h"
    57 
    58 #ifdef __CYGWIN__
    59 #define DISABLE_STDIO
    60 #endif
    61 
    62 /* This installs some signal handlers for the more common fatal signals,
    63    so that if the programmer is lazy, the app doesn't die so horribly if
    64    the program crashes.
    65 */
    66 
    67 static void print_msg(const char *text)
    68 {
    69 #ifndef DISABLE_STDIO
    70 	fprintf(stderr, "%s", text);
    71 #endif
    72 }
    73 
    74 static void SDL_Parachute(int sig)
    75 {
    76 	signal(sig, SIG_DFL);
    77 	print_msg("Fatal signal: ");
    78 	switch (sig) {
    79 		case SIGSEGV:
    80 			print_msg("Segmentation Fault");
    81 			break;
    82 #ifdef SIGBUS
    83 #if SIGBUS != SIGSEGV
    84 		case SIGBUS:
    85 			print_msg("Bus Error");
    86 			break;
    87 #endif
    88 #endif /* SIGBUS */
    89 #ifdef SIGFPE
    90 		case SIGFPE:
    91 			print_msg("Floating Point Exception");
    92 			break;
    93 #endif /* SIGFPE */
    94 #ifdef SIGQUIT
    95 		case SIGQUIT:
    96 			print_msg("Keyboard Quit");
    97 			break;
    98 #endif /* SIGQUIT */
    99 #ifdef SIGPIPE
   100 		case SIGPIPE:
   101 			print_msg("Broken Pipe");
   102 			break;
   103 #endif /* SIGPIPE */
   104 		default:
   105 #ifndef DISABLE_STDIO
   106 			fprintf(stderr, "# %d", sig);
   107 #endif
   108 			break;
   109 	}
   110 	print_msg(" (SDL Parachute Deployed)\n");
   111 	SDL_Quit();
   112 	exit(-sig);
   113 }
   114 
   115 static int SDL_fatal_signals[] = {
   116 	SIGSEGV,
   117 #ifdef SIGBUS
   118 	SIGBUS,
   119 #endif
   120 #ifdef SIGFPE
   121 	SIGFPE,
   122 #endif
   123 #ifdef SIGQUIT
   124 	SIGQUIT,
   125 #endif
   126 	0
   127 };
   128 
   129 void SDL_InstallParachute(void)
   130 {
   131 	/* Set a handler for any fatal signal not already handled */
   132 	int i;
   133 #ifdef HAVE_SIGACTION
   134 	struct sigaction action;
   135 
   136 	for ( i=0; SDL_fatal_signals[i]; ++i ) {
   137 		sigaction(SDL_fatal_signals[i], NULL, &action);
   138 		if ( action.sa_handler == SIG_DFL ) {
   139 			action.sa_handler = SDL_Parachute;
   140 			sigaction(SDL_fatal_signals[i], &action, NULL);
   141 		}
   142 	}
   143 #ifdef SIGALRM
   144 	/* Set SIGALRM to be ignored -- necessary on Solaris */
   145 	sigaction(SIGALRM, NULL, &action);
   146 	if ( action.sa_handler == SIG_DFL ) {
   147 		action.sa_handler = SIG_IGN;
   148 		sigaction(SIGALRM, &action, NULL);
   149 	}
   150 #endif
   151 #else
   152 	void (*ohandler)(int);
   153 
   154 	for ( i=0; SDL_fatal_signals[i]; ++i ) {
   155 		ohandler = signal(SDL_fatal_signals[i], SDL_Parachute);
   156 		if ( ohandler != SIG_DFL ) {
   157 			signal(SDL_fatal_signals[i], ohandler);
   158 		}
   159 	}
   160 #endif /* HAVE_SIGACTION */
   161 	return;
   162 }
   163 
   164 void SDL_UninstallParachute(void)
   165 {
   166 	/* Remove a handler for any fatal signal handled */
   167 	int i;
   168 #ifdef HAVE_SIGACTION
   169 	struct sigaction action;
   170 
   171 	for ( i=0; SDL_fatal_signals[i]; ++i ) {
   172 		sigaction(SDL_fatal_signals[i], NULL, &action);
   173 		if ( action.sa_handler == SDL_Parachute ) {
   174 			action.sa_handler = SIG_DFL;
   175 			sigaction(SDL_fatal_signals[i], &action, NULL);
   176 		}
   177 	}
   178 #else
   179 	void (*ohandler)(int);
   180 
   181 	for ( i=0; SDL_fatal_signals[i]; ++i ) {
   182 		ohandler = signal(SDL_fatal_signals[i], SIG_DFL);
   183 		if ( ohandler != SDL_Parachute ) {
   184 			signal(SDL_fatal_signals[i], ohandler);
   185 		}
   186 	}
   187 #endif /* HAVE_SIGACTION */
   188 }
   189 
   190 #endif /* NO_SIGNAL_H */