summaryrefslogtreecommitdiff
path: root/os/osinit.c
diff options
context:
space:
mode:
authorAlan Coopersmith <alan.coopersmith@sun.com>2009-03-09 13:22:57 -0700
committerAlan Coopersmith <alan.coopersmith@sun.com>2009-04-09 17:10:12 -0700
commita0b6a363dca8ce0dc6f4eb79333e48496153cd67 (patch)
treee67b9bb7ba752daf740905818cb26e6b110ac31a /os/osinit.c
parentfcc19e673e3ef33d64916dd933853f8aa667c4d7 (diff)
Lift fatal signal handlers from DDX'es up to a common DIX implementation
Signed-off-by: Alan Coopersmith <alan.coopersmith@sun.com>
Diffstat (limited to 'os/osinit.c')
-rw-r--r--os/osinit.c83
1 files changed, 83 insertions, 0 deletions
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 <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);