[PATCH] Lift fatal signal handlers from DDX'es up to a common DIX implementation

Alan Coopersmith alan.coopersmith at sun.com
Tue Mar 31 11:23:26 PDT 2009


Signed-off-by: Alan Coopersmith <alan.coopersmith at sun.com>
---
 hw/kdrive/src/kdrive.c         |   34 ++--------------
 hw/xfree86/common/xf86Events.c |   28 +++----------
 hw/xfree86/common/xf86Init.c   |   18 +++++----
 hw/xfree86/common/xf86Priv.h   |    2 +-
 include/os.h                   |    2 +
 os/log.c                       |    7 +++
 os/osinit.c                    |   83 ++++++++++++++++++++++++++++++++++++++++
 7 files changed, 113 insertions(+), 61 deletions(-)

diff --git a/hw/kdrive/src/kdrive.c b/hw/kdrive/src/kdrive.c
index 97d167e..80165ed 100644
--- a/hw/kdrive/src/kdrive.c
+++ b/hw/kdrive/src/kdrive.c
@@ -1290,38 +1290,12 @@ KdDepthToFb (ScreenPtr	pScreen, int depth)
 
 #endif
 
-#ifdef HAVE_BACKTRACE
-/* shamelessly ripped from xf86Events.c */
-void
-KdBacktrace (int signum)
-{
-    void *array[32]; /* more than 32 and you have bigger problems */
-    size_t size, i;
-    char **strings;
-
-    signal(signum, SIG_IGN);
-
-    size = backtrace (array, 32);
-    fprintf (stderr, "\nBacktrace (%d deep):\n", size);
-    strings = backtrace_symbols (array, size);
-    for (i = 0; i < size; i++)
-        fprintf (stderr, "%d: %s\n", i, strings[i]);
-    free (strings);
-    
-    kdCaughtSignal = TRUE;    
-    if (signum == SIGSEGV)
-        FatalError("Segmentation fault caught\n");
-    else if (signum > 0)
-        FatalError("Signal %d caught\n", signum);
-}
-#else
-void
-KdBacktrace (int signum)
+static int
+KdSignalWrapper (int signum)
 {
     kdCaughtSignal = TRUE;
-    FatalError("Segmentation fault caught\n");
+    return 1; /* use generic OS layer cleanup & abort */
 }
-#endif
 
 void
 KdInitOutput (ScreenInfo    *pScreenInfo,
@@ -1368,7 +1342,7 @@ KdInitOutput (ScreenInfo    *pScreenInfo,
 	for (screen = card->screenList; screen; screen = screen->next)
 	    KdAddScreen (pScreenInfo, screen, argc, argv);
 
-    signal(SIGSEGV, KdBacktrace);
+    OsRegisterSigWrapper(KdSignalWrapper);
 }
 
 void
diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c
index 9ed2884..16af919 100644
--- a/hw/xfree86/common/xf86Events.c
+++ b/hw/xfree86/common/xf86Events.c
@@ -79,11 +79,6 @@
 #include "xkbsrv.h"
 #include "xkbstr.h"
 
-#ifdef XF86BIGFONT
-#define _XF86BIGFONT_SERVER_
-#include <X11/extensions/xf86bigfont.h>
-#endif
-
 #ifdef DPMSExtension
 #define DPMS_SERVER
 #include <X11/extensions/dpms.h>
@@ -356,35 +351,24 @@ xf86InterceptSigIll(void (*sigillhandler)(void))
 }
 
 /*
- * xf86SigHandler --
+ * xf86SigWrapper --
  *    Catch unexpected signals and exit or continue cleanly.
  */
-void
-xf86SigHandler(int signo)
+int
+xf86SigWrapper(int signo)
 {
   if ((signo == SIGILL) && xf86SigIllHandler) {
     (*xf86SigIllHandler)();
-    /* Re-arm handler just in case we unexpectedly return here */
-    (void) signal(signo, xf86SigHandler);
-    return;
+    return 0; /* continue */
   }
 
   if (xf86SignalIntercept && (*xf86SignalIntercept < 0)) {
     *xf86SignalIntercept = signo;
-    /* Re-arm handler just in case */
-    (void) signal(signo, xf86SigHandler);
-    return;
+    return 0; /* continue */
   }
 
-  signal(signo,SIG_IGN);
   xf86Info.caughtSignal = TRUE;
-#ifdef XF86BIGFONT
-  XF86BigfontCleanup();
-#endif
-
-  xorg_backtrace();
-
-  FatalError("Caught signal %d.  Server aborting\n", signo);
+  return 1; /* abort */
 }
 
 /*
diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c
index acb775b..cf28ae7 100644
--- a/hw/xfree86/common/xf86Init.c
+++ b/hw/xfree86/common/xf86Init.c
@@ -380,23 +380,25 @@ InstallSignalHandlers(void)
      */
     xf86Info.caughtSignal=FALSE;
     if (!xf86Info.notrapSignals) {
-       signal(SIGSEGV,xf86SigHandler);
-       signal(SIGILL,xf86SigHandler);
+	OsRegisterSigWrapper(xf86SigWrapper);
+    } else {
+	signal(SIGSEGV, SIG_DFL);
+	signal(SIGILL, SIG_DFL);
 #ifdef SIGEMT
-       signal(SIGEMT,xf86SigHandler);
+	signal(SIGEMT, SIG_DFL);
 #endif
-       signal(SIGFPE,xf86SigHandler);
+	signal(SIGFPE, SIG_DFL);
 #ifdef SIGBUS
-       signal(SIGBUS,xf86SigHandler);
+	signal(SIGBUS, SIG_DFL);
 #endif
 #ifdef SIGSYS
-       signal(SIGSYS,xf86SigHandler);
+	signal(SIGSYS, SIG_DFL);
 #endif
 #ifdef SIGXCPU
-       signal(SIGXCPU,xf86SigHandler);
+	signal(SIGXCPU, SIG_DFL);
 #endif
 #ifdef SIGXFSZ
-       signal(SIGXFSZ,xf86SigHandler);
+	signal(SIGXFSZ, SIG_DFL);
 #endif
     }
 }
diff --git a/hw/xfree86/common/xf86Priv.h b/hw/xfree86/common/xf86Priv.h
index 6d53277..5b67663 100644
--- a/hw/xfree86/common/xf86Priv.h
+++ b/hw/xfree86/common/xf86Priv.h
@@ -150,7 +150,7 @@ extern _X_EXPORT void DoShowOptions(void);
 /* xf86Events.c */
 
 extern _X_EXPORT void xf86Wakeup(pointer blockData, int err, pointer pReadmask);
-extern _X_EXPORT void xf86SigHandler(int signo);
+extern _X_HIDDEN int xf86SigWrapper(int signo);
 extern _X_EXPORT void xf86HandlePMEvents(int fd, pointer data);
 extern _X_EXPORT int (*xf86PMGetEventFromOs)(int fd,pmEvent *events,int num);
 extern _X_EXPORT pmWait (*xf86PMConfirmEventToOs)(int fd,pmEvent event);
diff --git a/include/os.h b/include/os.h
index 7da31a5..8d88f6b 100644
--- a/include/os.h
+++ b/include/os.h
@@ -235,8 +235,10 @@ extern _X_EXPORT char *XNFprintf(const char *fmt, ...);
 extern _X_EXPORT char *XNFvprintf(const char *fmt, va_list va);
 
 typedef SIGVAL (*OsSigHandlerPtr)(int /* sig */);
+typedef int (*OsSigWrapperPtr)(int /* sig */);
 
 extern _X_EXPORT OsSigHandlerPtr OsSignal(int /* sig */, OsSigHandlerPtr /* handler */);
+extern _X_EXPORT OsSigWrapperPtr OsRegisterSigWrapper(OsSigWrapperPtr newWrap);
 
 extern _X_EXPORT int auditTrailLevel;
 
diff --git a/os/log.c b/os/log.c
index b01965a..3961b0b 100644
--- a/os/log.c
+++ b/os/log.c
@@ -98,6 +98,10 @@ OR PERFORMANCE OF THIS SOFTWARE.
 #define getpid(x) _getpid(x)
 #endif
 
+#ifdef XF86BIGFONT
+#define _XF86BIGFONT_SERVER_
+#include <X11/extensions/xf86bigfont.h>
+#endif
 
 #ifdef DDXOSVERRORF
 void (*OsVendorVErrorFProc)(const char *, va_list args) = NULL;
@@ -401,6 +405,9 @@ void AbortServer(void) __attribute__((noreturn));
 void
 AbortServer(void)
 {
+#ifdef XF86BIGFONT
+    XF86BigfontCleanup();
+#endif
     CloseWellKnownConnections();
     OsCleanup(TRUE);
     CloseDownDevices();
diff --git a/os/osinit.c b/os/osinit.c
index f9ee73e..34d8378 100644
--- a/os/osinit.c
+++ b/os/osinit.c
@@ -54,6 +54,8 @@ SOFTWARE.
 #include "os.h"
 #include "osdep.h"
 #include <X11/Xos.h>
+#include <signal.h>
+#include <errno.h>
 
 #include "dixstruct.h"
 
@@ -88,6 +90,58 @@ int limitStackSpace = -1;
 int limitNoFile = -1;
 #endif
 
+static OsSigWrapperPtr OsSigWrapper = NULL;
+
+OsSigWrapperPtr
+OsRegisterSigWrapper(OsSigWrapperPtr newSigWrapper)
+{
+    OsSigWrapperPtr oldSigWrapper = OsSigWrapper;
+
+    OsSigWrapper = newSigWrapper;
+
+    return oldSigWrapper;
+}
+
+/*
+ * OsSigHandler --
+ *    Catch unexpected signals and exit or continue cleanly.
+ */
+static void
+#ifdef SA_SIGINFO
+OsSigHandler(int signo, siginfo_t *sip, void *unused)
+#else
+OsSigHandler(int signo)
+#endif
+{
+  if (OsSigWrapper != NULL) {
+      if (OsSigWrapper(signo) == 0) {
+	  /* ddx handled signal and wants us to continue */
+	  return;
+      }
+  }
+
+  /* log, cleanup, and abort */
+  xorg_backtrace();
+
+#ifdef SA_SIGINFO
+  if (sip->si_code == SI_USER) {
+      ErrorF("Recieved signal %d sent by process %ld, uid %ld\n",
+	     (long) sip->si_pid, (long) sip->si_uid);
+  } else {
+      switch (signo) {
+          case SIGSEGV:
+          case SIGBUS:
+          case SIGILL:
+          case SIGFPE:
+	      ErrorF("%s at address %p\n", strsignal(signo), sip->si_addr);
+      }
+  }
+#endif
+
+  FatalError("Caught signal %d (%s). Server aborting\n",
+	     signo, strsignal(signo));
+}
+
 void
 OsInit(void)
 {
@@ -97,6 +151,35 @@ OsInit(void)
     char fname[PATH_MAX];
 
     if (!been_here) {
+	struct sigaction act, oact;
+	int i;
+	int siglist[] = { SIGSEGV, SIGQUIT, SIGILL, SIGFPE, SIGBUS,
+#ifdef SIGSYS
+			  SIGSYS,
+#endif
+#ifdef SIGXCPU
+			  SIGXCPU,
+#endif
+#ifdef SIGXFSZ
+			  SIGXFSZ,
+#endif
+#ifdef SIGEMT
+			  SIGEMT,
+#endif
+			  0 /* must be last */ };
+	sigemptyset(&act.sa_mask);
+	act.sa_handler = OsSigHandler;
+	act.sa_flags = 0;
+#ifdef SA_SIGINFO
+	act.sa_flags |= SA_SIGINFO;
+#endif
+	for (i = 0; siglist[i] != 0; i++) {
+	    if (sigaction(siglist[i], &act, &oact)) {
+		ErrorF("failed to install signal handler for signal %d: %s\n",
+		       siglist[i], strerror(errno));
+	    }
+	}
+
 #if !defined(__SCO__) && !defined(__CYGWIN__) && !defined(__UNIXWARE__)
 	fclose(stdin);
 	fclose(stdout);
-- 
1.5.6.5



More information about the xorg-devel mailing list