Do not break application's signal handler installed with SA_SIGINFO
authorSam Lantinga <slouken@libsdl.org>
Tue, 15 Mar 2011 21:37:01 -0700
changeset 5493 a8849b1193c3
parent 5491 abdd970a65a8
child 5494 78b351c52f53
Do not break application's signal handler installed with SA_SIGINFO Gleb Natapov to sdl If application installs SIGINT/SIGTERM signal handler with sigaction(SA_SIGINFO) syscall before initializing SDL, after initialization of SDL signal handler will be reinstalled without SA_SIGINFO flag which brings havoc when the signal handler is called. The breakage is done by SDL_QuitInit()/SDL_QuitQuit() function. They use signal() to detect that signal handler is already installed even in sigaction() is available.
src/events/SDL_quit.c
--- a/src/events/SDL_quit.c	Tue Mar 15 19:37:38 2011 -0700
+++ b/src/events/SDL_quit.c	Tue Mar 15 21:37:01 2011 -0700
@@ -47,7 +47,19 @@
 int
 SDL_QuitInit(void)
 {
-#ifdef HAVE_SIGNAL_H
+#ifdef HAVE_SIGACTION
+    struct sigaction action;
+    sigaction(SIGINT, NULL, &action);
+    if ( action.sa_handler == SIG_DFL && action.sa_sigaction == SIG_DFL ) {
+        action.sa_handler = SDL_HandleSIG;
+        sigaction(SIGINT, &action, NULL);
+    }
+    sigaction(SIGTERM, NULL, &action);
+    if ( action.sa_handler == SIG_DFL && action.sa_sigaction == SIG_DFL ) {
+        action.sa_handler = SDL_HandleSIG;
+        sigaction(SIGTERM, &action, NULL);
+    }
+#elif HAVE_SIGNAL_H
     void (*ohandler) (int);
 
     /* Both SIGINT and SIGTERM are translated into quit interrupts */
@@ -66,7 +78,19 @@
 void
 SDL_QuitQuit(void)
 {
-#ifdef HAVE_SIGNAL_H
+#ifdef HAVE_SIGACTION
+    struct sigaction action;
+    sigaction(SIGINT, NULL, &action);
+    if ( action.sa_handler == SDL_HandleSIG ) {
+        action.sa_handler = SIG_DFL;
+        sigaction(SIGINT, &action, NULL);
+    }
+    sigaction(SIGTERM, NULL, &action);
+    if ( action.sa_handler == SDL_HandleSIG ) {
+        action.sa_handler = SIG_DFL;
+        sigaction(SIGTERM, &action, NULL);
+    }
+#elif HAVE_SIGNAL_H
     void (*ohandler) (int);
 
     ohandler = signal(SIGINT, SIG_DFL);