[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