src/SDL_fatal.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 12 Feb 2004 16:29:24 +0000
changeset 814 5a417d2a8603
parent 769 b8d311d90021
child 822 abb915adb1b0
permissions -rw-r--r--
Use sigaction instead of signal to preserve handler flags (thanks Matthew!)
     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 /* General fatal signal handling code for SDL */
    29 
    30 #ifdef NO_SIGNAL_H
    31 
    32 /* No signals on this platform, nothing to do.. */
    33 
    34 void SDL_InstallParachute(void)
    35 {
    36 	return;
    37 }
    38 
    39 void SDL_UninstallParachute(void)
    40 {
    41 	return;
    42 }
    43 
    44 #else
    45 
    46 #include <stdlib.h>
    47 #include <stdio.h>
    48 #include <signal.h>
    49 #include <string.h>
    50 
    51 #include "SDL.h"
    52 #include "SDL_fatal.h"
    53 
    54 #ifdef __CYGWIN__
    55 #define DISABLE_STDIO
    56 #endif
    57 
    58 /* This installs some signal handlers for the more common fatal signals,
    59    so that if the programmer is lazy, the app doesn't die so horribly if
    60    the program crashes.
    61 */
    62 
    63 static void print_msg(const char *text)
    64 {
    65 #ifndef DISABLE_STDIO
    66 	fprintf(stderr, "%s", text);
    67 #endif
    68 }
    69 
    70 static void SDL_Parachute(int sig)
    71 {
    72 	signal(sig, SIG_DFL);
    73 	print_msg("Fatal signal: ");
    74 	switch (sig) {
    75 		case SIGSEGV:
    76 			print_msg("Segmentation Fault");
    77 			break;
    78 #ifdef SIGBUS
    79 #if SIGBUS != SIGSEGV
    80 		case SIGBUS:
    81 			print_msg("Bus Error");
    82 			break;
    83 #endif
    84 #endif /* SIGBUS */
    85 #ifdef SIGFPE
    86 		case SIGFPE:
    87 			print_msg("Floating Point Exception");
    88 			break;
    89 #endif /* SIGFPE */
    90 #ifdef SIGQUIT
    91 		case SIGQUIT:
    92 			print_msg("Keyboard Quit");
    93 			break;
    94 #endif /* SIGQUIT */
    95 #ifdef SIGPIPE
    96 		case SIGPIPE:
    97 			print_msg("Broken Pipe");
    98 			break;
    99 #endif /* SIGPIPE */
   100 		default:
   101 #ifndef DISABLE_STDIO
   102 			fprintf(stderr, "# %d", sig);
   103 #endif
   104 			break;
   105 	}
   106 	print_msg(" (SDL Parachute Deployed)\n");
   107 	SDL_Quit();
   108 	exit(-sig);
   109 }
   110 
   111 static int SDL_fatal_signals[] = {
   112 	SIGSEGV,
   113 #ifdef SIGBUS
   114 	SIGBUS,
   115 #endif
   116 #ifdef SIGFPE
   117 	SIGFPE,
   118 #endif
   119 #ifdef SIGQUIT
   120 	SIGQUIT,
   121 #endif
   122 #ifdef SIGPIPE
   123 	SIGPIPE,
   124 #endif
   125 	0
   126 };
   127 
   128 void SDL_InstallParachute(void)
   129 {
   130 	/* Set a handler for any fatal signal not already handled */
   131 	int i;
   132 #ifdef HAVE_SIGACTION
   133 	struct sigaction action;
   134 
   135 	for ( i=0; SDL_fatal_signals[i]; ++i ) {
   136 		sigaction(SDL_fatal_signals[i], NULL, &action);
   137 		if ( action.sa_handler == SIG_DFL ) {
   138 			action.sa_handler = SDL_Parachute;
   139 			sigaction(SDL_fatal_signals[i], &action, NULL);
   140 		}
   141 	}
   142 #ifdef SIGALRM
   143 	/* Set SIGALRM to be ignored -- necessary on Solaris */
   144 	sigaction(SIGALRM, NULL, &action);
   145 	if ( action.sa_handler == SIG_DFL ) {
   146 		action.sa_handler = SIG_IGN;
   147 		sigaction(SDL_fatal_signals[i], &action, NULL);
   148 	}
   149 #endif
   150 #else
   151 	void (*ohandler)(int);
   152 
   153 	for ( i=0; SDL_fatal_signals[i]; ++i ) {
   154 		ohandler = signal(SDL_fatal_signals[i], SDL_Parachute);
   155 		if ( ohandler != SIG_DFL ) {
   156 			signal(SDL_fatal_signals[i], ohandler);
   157 		}
   158 	}
   159 #endif /* HAVE_SIGACTION */
   160 	return;
   161 }
   162 
   163 void SDL_UninstallParachute(void)
   164 {
   165 	/* Remove a handler for any fatal signal handled */
   166 	int i;
   167 #ifdef HAVE_SIGACTION
   168 	struct sigaction action;
   169 
   170 	for ( i=0; SDL_fatal_signals[i]; ++i ) {
   171 		sigaction(SDL_fatal_signals[i], NULL, &action);
   172 		if ( action.sa_handler == SDL_Parachute ) {
   173 			action.sa_handler = SIG_DFL;
   174 			sigaction(SDL_fatal_signals[i], &action, NULL);
   175 		}
   176 	}
   177 #else
   178 	void (*ohandler)(int);
   179 
   180 	for ( i=0; SDL_fatal_signals[i]; ++i ) {
   181 		ohandler = signal(SDL_fatal_signals[i], SIG_DFL);
   182 		if ( ohandler != SDL_Parachute ) {
   183 			signal(SDL_fatal_signals[i], ohandler);
   184 		}
   185 	}
   186 #endif /* HAVE_SIGACTION */
   187 }
   188 
   189 #endif /* NO_SIGNAL_H */