From a0b6a363dca8ce0dc6f4eb79333e48496153cd67 Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Mon, 9 Mar 2009 13:22:57 -0700 Subject: [PATCH] Lift fatal signal handlers from DDX'es up to a common DIX implementation Signed-off-by: Alan Coopersmith --- 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 76355e8a1..ccef2a0c8 100644 --- a/hw/kdrive/src/kdrive.c +++ b/hw/kdrive/src/kdrive.c @@ -1279,38 +1279,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, @@ -1357,7 +1331,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 19120cede..aa818c358 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 -#endif - #ifdef DPMSExtension #define DPMS_SERVER #include @@ -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 acb775bbe..cf28ae73e 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 bc984f2f7..f4ed8c085 100644 --- a/hw/xfree86/common/xf86Priv.h +++ b/hw/xfree86/common/xf86Priv.h @@ -147,7 +147,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 bda7125a0..2f6b0c06f 100644 --- a/include/os.h +++ b/include/os.h @@ -228,8 +228,10 @@ extern _X_EXPORT char *XNFprintf(const char *fmt, ...); extern _X_EXPORT char *XNFvprintf(const char *fmt, va_list va); typedef void (*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 b01965a17..3961b0b9f 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 +#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 f9ee73ec1..34d8378a6 100644 --- a/os/osinit.c +++ b/os/osinit.c @@ -54,6 +54,8 @@ SOFTWARE. #include "os.h" #include "osdep.h" #include +#include +#include #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);