>From 8718ed739d79d4792362172fee3c6bcdea8c5721 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 23 Apr 2008 16:04:08 +0930 Subject: [PATCH] dix: set up siglongjmp to jump to in case of a FatalError. Calling FatalError from within xf86SignalHandler is not POSIX compliant (it calls free() on the way out). So we set up a siglongjmp environment at the start of main() and jump back here before we bring the server down. --- dix/main.c | 16 ++++++++++++++++ hw/xfree86/common/xf86Events.c | 9 ++++++++- include/dix.h | 4 ++++ 3 files changed, 28 insertions(+), 1 deletions(-) diff --git a/dix/main.c b/dix/main.c index f7824ee..cc17416 100644 --- a/dix/main.c +++ b/dix/main.c @@ -119,6 +119,12 @@ Equipment Corporation. #include "dpmsproc.h" #endif +/** + * siglongjmp environment set up in Dispatch(). Used by xf86SignalHandler to + * jump out when a FatalError is needed. + */ +sigjmp_buf sigjmp_env; + extern void Dispatch(void); char *ConnectionInfo; @@ -247,9 +253,19 @@ main(int argc, char *argv[], char *envp[]) int i, j, k, error; char *xauthfile; HWEventQueueType alwaysCheckForInput[2]; + int sig; display = "0"; + + /* Set up a signal longjump. If a SEGV or other signal will bring the + * server down, we jump here to be able to FatalError(). + */ + if ((sig = sigsetjmp(sigjmp_env, 0))) + { + FatalError("Aborting after receiving signal %d.\n", sig); + } + InitGlobals(); InitRegions(); #ifdef XPRINT diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c index d1e4393..a07f066 100644 --- a/hw/xfree86/common/xf86Events.c +++ b/hw/xfree86/common/xf86Events.c @@ -125,6 +125,7 @@ _X_EXPORT Bool VTSwitchEnabled = TRUE; /* Allows run-time disabling for *BSD and for avoiding VT switches when using the DRI automatic full screen mode.*/ +extern sigjmp_buf sigjmp_env; extern fd_set EnabledDevices; @@ -764,8 +765,14 @@ xf86SigHandler(int signo) #endif xorg_backtrace(); + ErrorF("Caught signal %d. Server aborting.\n", signo); - FatalError("Caught signal %d. Server aborting\n", signo); + /* Do not call FatalError() here. It will close down the devices and thus + * call free(), which is a no-no from within a signal handler. + * We have to siglongjmp out of here before we bring the server down. + * The sig longjmp environment was set up first thin in main(). + */ + siglongjmp(sigjmp_env, signo); } static void diff --git a/include/dix.h b/include/dix.h index 57ffee9..014c8f6 100644 --- a/include/dix.h +++ b/include/dix.h @@ -47,6 +47,7 @@ SOFTWARE. #ifndef DIX_H #define DIX_H +#include #include "gc.h" #include "window.h" @@ -305,6 +306,9 @@ extern void InitAtoms(void); /* main.c */ +/* Environment for siglongjmp. Will be set up in main(). */ +extern sigjmp_buf sigjmp_env; + extern void SetVendorRelease(int release); extern void SetVendorString(char *string); -- 1.5.3