From fc8f37239f3af088819c18f5632b2608954af73a Mon Sep 17 00:00:00 2001
From: marha <marha@users.sourceforge.net>
Date: Wed, 4 Jul 2012 10:36:18 +0200
Subject: mesa xserver git update 4 Jul 2012

---
 xorg-server/configure.ac                         |  20 +++
 xorg-server/dix/dixfonts.c                       |   9 ++
 xorg-server/dix/getevents.c                      |   4 +-
 xorg-server/dix/touch.c                          |   5 +-
 xorg-server/hw/xfree86/Makefile.am               |   6 +-
 xorg-server/hw/xfree86/common/xf86Init.c         |  14 +-
 xorg-server/hw/xfree86/common/xf86Module.h       |   2 +-
 xorg-server/hw/xfree86/common/xf86Xinput.h       |   6 +-
 xorg-server/hw/xfree86/dri/Makefile.am           |   2 +-
 xorg-server/hw/xfree86/dri2/Makefile.am          |   2 +-
 xorg-server/hw/xfree86/i2c/Makefile.am           |   5 +-
 xorg-server/hw/xfree86/loader/loader.c           |   2 +-
 xorg-server/hw/xfree86/loader/loadmod.c          |   5 +-
 xorg-server/hw/xfree86/os-support/shared/sigio.c |   4 +
 xorg-server/hw/xfree86/xaa/Makefile.am           |   3 +-
 xorg-server/include/dixfont.h                    |  13 +-
 xorg-server/include/globals.h                    |   3 +
 xorg-server/include/misc.h                       |  10 +-
 xorg-server/include/os.h                         |  13 ++
 xorg-server/mi/mieq.c                            |  19 ++-
 xorg-server/os/backtrace.c                       |  49 ++++---
 xorg-server/os/log.c                             | 175 ++++++++++++++++++++++-
 xorg-server/os/osinit.c                          |   8 +-
 xorg-server/os/utils.c                           |  46 ++++++
 xorg-server/test/.gitignore                      |   1 +
 xorg-server/test/Makefile.am                     |   3 +-
 xorg-server/test/signal-logging.c                | 115 +++++++++++++++
 27 files changed, 467 insertions(+), 77 deletions(-)
 create mode 100644 xorg-server/test/signal-logging.c

(limited to 'xorg-server')

diff --git a/xorg-server/configure.ac b/xorg-server/configure.ac
index 7576dae1d..d5ddf6e10 100644
--- a/xorg-server/configure.ac
+++ b/xorg-server/configure.ac
@@ -1499,6 +1499,26 @@ case "$host_os" in
 	XORG_DRIVER_LIBS="-lXorg.exe -L\${moduledir} -lshadow -lfb -no-undefined"
 	CYGWIN=yes
 	;;
+    solaris*)
+	# We use AC_LINK_IFELSE to generate a temporary program conftest$EXEEXT
+	# that we can link against for testing if the system linker is new
+	# enough to support -z parent=<program> for verifying loadable modules
+	# are only calling functions defined in either the loading program or
+	# the libraries they're linked with.
+	AC_LINK_IFELSE(
+	    [AC_LANG_SOURCE([int main(int argc, char **argv) { return 0; }])],
+	    [mv conftest$EXEEXT conftest.parent
+	     XORG_CHECK_LINKER_FLAGS([-Wl,-z,parent=conftest.parent -G],
+		[LD_NO_UNDEFINED_FLAG="-Wl,-z,defs -Wl,-z,parent=\$(top_builddir)/hw/xfree86/Xorg"
+# Not set yet, since this gets exported in xorg-server.pc to all the drivers,
+# and they're not all fixed to build correctly with it yet.
+#		 XORG_DRIVER_LIBS="-Wl,-z,defs -Wl,-z,parent=${bindir}/Xorg"
+         ],[],
+		[AC_LANG_SOURCE([extern int main(int argc, char **argv);
+			int call_main(void) { return main(0, NULL); }])])
+	     rm -f conftest.parent
+	    ])
+	;;
 esac
 AC_SUBST([LD_EXPORT_SYMBOLS_FLAG])
 AC_SUBST([LD_NO_UNDEFINED_FLAG])
diff --git a/xorg-server/dix/dixfonts.c b/xorg-server/dix/dixfonts.c
index 19fd31e3e..dd9331195 100644
--- a/xorg-server/dix/dixfonts.c
+++ b/xorg-server/dix/dixfonts.c
@@ -115,6 +115,15 @@ LoadGlyphs(ClientPtr client, FontPtr pfont, unsigned nchars, int item_size,
         return Successful;
 }
 
+void
+dixGetGlyphs(FontPtr font, unsigned long count, unsigned char *chars,
+             FontEncoding fontEncoding,
+             unsigned long *glyphcount,    /* RETURN */
+             CharInfoPtr *glyphs)          /* RETURN */
+{
+    (*font->get_glyphs) (font, count, chars, fontEncoding, glyphcount, glyphs);
+}
+
 /*
  * adding RT_FONT prevents conflict with default cursor font
  */
diff --git a/xorg-server/dix/getevents.c b/xorg-server/dix/getevents.c
index 75708520f..27c2e04d1 100644
--- a/xorg-server/dix/getevents.c
+++ b/xorg-server/dix/getevents.c
@@ -1867,8 +1867,8 @@ GetTouchEvents(InternalEvent *events, DeviceIntPtr dev, uint32_t ddx_touchid,
         touchpoint.ti =
             TouchFindByDDXID(dev, ddx_touchid, (type == XI_TouchBegin));
         if (!touchpoint.ti) {
-            ErrorF("[dix] %s: unable to %s touch point %x\n", dev->name,
-                   type == XI_TouchBegin ? "begin" : "find", ddx_touchid);
+            ErrorFSigSafe("[dix] %s: unable to %s touch point %u\n", dev->name,
+                          type == XI_TouchBegin ? "begin" : "find", ddx_touchid);
             return 0;
         }
         client_id = touchpoint.ti->client_id;
diff --git a/xorg-server/dix/touch.c b/xorg-server/dix/touch.c
index aa17faf28..a01f152cd 100644
--- a/xorg-server/dix/touch.c
+++ b/xorg-server/dix/touch.c
@@ -198,8 +198,9 @@ TouchBeginDDXTouch(DeviceIntPtr dev, uint32_t ddx_id)
     /* If we get here, then we've run out of touches and we need to drop the
      * event (we're inside the SIGIO handler here) schedule a WorkProc to
      * grow the queue for us for next time. */
-    ErrorF("%s: not enough space for touch events (max %d touchpoints). "
-           "Dropping this event.\n", dev->name, dev->last.num_touches);
+    ErrorFSigSafe("%s: not enough space for touch events (max %u touchpoints). "
+                  "Dropping this event.\n", dev->name, dev->last.num_touches);
+
     if (!BitIsOn(resize_waiting, dev->id)) {
         SetBit(resize_waiting, dev->id);
         QueueWorkProc(TouchResizeQueue, serverClient, NULL);
diff --git a/xorg-server/hw/xfree86/Makefile.am b/xorg-server/hw/xfree86/Makefile.am
index e50cb88c2..4d5d576a3 100644
--- a/xorg-server/hw/xfree86/Makefile.am
+++ b/xorg-server/hw/xfree86/Makefile.am
@@ -26,9 +26,9 @@ INT10_SUBDIR = int10
 endif
 
 SUBDIRS = common ddc x86emu $(INT10_SUBDIR) os-support parser \
-	  ramdac $(VBE_SUBDIR) $(VGAHW_SUBDIR) $(XAA_SUBDIR) \
-	  loader modes . i2c dixmods fbdevhw shadowfb exa \
-	  $(DRI_SUBDIR) $(DRI2_SUBDIR) $(XF86UTILS_SUBDIR) doc man
+	  ramdac $(VGAHW_SUBDIR) loader modes . $(VBE_SUBDIR) \
+	  $(XAA_SUBDIR) $(DRI_SUBDIR) $(DRI2_SUBDIR) i2c dixmods \
+	  fbdevhw shadowfb exa $(XF86UTILS_SUBDIR) doc man
 
 DIST_SUBDIRS = common ddc i2c x86emu int10 fbdevhw os-support \
                parser ramdac shadowfb vbe vgahw xaa \
diff --git a/xorg-server/hw/xfree86/common/xf86Init.c b/xorg-server/hw/xfree86/common/xf86Init.c
index ca6efd44e..84c866944 100644
--- a/xorg-server/hw/xfree86/common/xf86Init.c
+++ b/xorg-server/hw/xfree86/common/xf86Init.c
@@ -1058,16 +1058,16 @@ void
 OsVendorFatalError(const char *f, va_list args)
 {
 #ifdef VENDORSUPPORT
-    ErrorF("\nPlease refer to your Operating System Vendor support pages\n"
-           "at %s for support on this crash.\n", VENDORSUPPORT);
+    ErrorFSigSafe("\nPlease refer to your Operating System Vendor support "
+                 "pages\nat %s for support on this crash.\n", VENDORSUPPORT);
 #else
-    ErrorF("\nPlease consult the " XVENDORNAME " support \n"
-           "\t at " __VENDORDWEBSUPPORT__ "\n for help. \n");
+    ErrorFSigSafe("\nPlease consult the " XVENDORNAME " support \n\t at "
+                 __VENDORDWEBSUPPORT__ "\n for help. \n");
 #endif
     if (xf86LogFile && xf86LogFileWasOpened)
-        ErrorF("Please also check the log file at \"%s\" for additional "
-               "information.\n", xf86LogFile);
-    ErrorF("\n");
+        ErrorFSigSafe("Please also check the log file at \"%s\" for additional "
+                     "information.\n", xf86LogFile);
+    ErrorFSigSafe("\n");
 }
 
 int
diff --git a/xorg-server/hw/xfree86/common/xf86Module.h b/xorg-server/hw/xfree86/common/xf86Module.h
index bf56acd05..7671cea5d 100644
--- a/xorg-server/hw/xfree86/common/xf86Module.h
+++ b/xorg-server/hw/xfree86/common/xf86Module.h
@@ -83,7 +83,7 @@ typedef enum {
  */
 #define ABI_ANSIC_VERSION	SET_ABI_VERSION(0, 4)
 #define ABI_VIDEODRV_VERSION	SET_ABI_VERSION(13, 0)
-#define ABI_XINPUT_VERSION	SET_ABI_VERSION(17, 0)
+#define ABI_XINPUT_VERSION	SET_ABI_VERSION(18, 0)
 #define ABI_EXTENSION_VERSION	SET_ABI_VERSION(6, 0)
 #define ABI_FONT_VERSION	SET_ABI_VERSION(0, 6)
 
diff --git a/xorg-server/hw/xfree86/common/xf86Xinput.h b/xorg-server/hw/xfree86/common/xf86Xinput.h
index 1d4363a50..35c38a554 100644
--- a/xorg-server/hw/xfree86/common/xf86Xinput.h
+++ b/xorg-server/hw/xfree86/common/xf86Xinput.h
@@ -68,14 +68,14 @@
 /* This holds the input driver entry and module information. */
 typedef struct _InputDriverRec {
     int driverVersion;
-    char *driverName;
+    const char *driverName;
     void (*Identify) (int flags);
     int (*PreInit) (struct _InputDriverRec * drv,
                     struct _InputInfoRec * pInfo, int flags);
     void (*UnInit) (struct _InputDriverRec * drv,
                     struct _InputInfoRec * pInfo, int flags);
     pointer module;
-    char **default_options;
+    const char **default_options;
 } InputDriverRec, *InputDriverPtr;
 
 /* This is to input devices what the ScrnInfoRec is to screens. */
@@ -98,7 +98,7 @@ typedef struct _InputInfoRec {
     int fd;
     DeviceIntPtr dev;
     pointer private;
-    char *type_name;
+    const char *type_name;
     InputDriverPtr drv;
     pointer module;
     XF86OptionPtr options;
diff --git a/xorg-server/hw/xfree86/dri/Makefile.am b/xorg-server/hw/xfree86/dri/Makefile.am
index 194cf8e3f..9528d5370 100644
--- a/xorg-server/hw/xfree86/dri/Makefile.am
+++ b/xorg-server/hw/xfree86/dri/Makefile.am
@@ -13,7 +13,7 @@ libdri_la_CFLAGS = -I$(top_srcdir)/hw/xfree86/common \
                    @LIBDRM_CFLAGS@ \
                    @DRI_CFLAGS@
 libdri_la_LDFLAGS = -module -avoid-version $(LD_NO_UNDEFINED_FLAG)
-libdri_la_LIBADD = @LIBDRM_LIBS@
+libdri_la_LIBADD = @LIBDRM_LIBS@ $(PIXMAN_LIBS)
 libdri_ladir = $(moduledir)/extensions
 libdri_la_SOURCES = \
 	dri.c \
diff --git a/xorg-server/hw/xfree86/dri2/Makefile.am b/xorg-server/hw/xfree86/dri2/Makefile.am
index 0e40fbcf2..390ed12c8 100644
--- a/xorg-server/hw/xfree86/dri2/Makefile.am
+++ b/xorg-server/hw/xfree86/dri2/Makefile.am
@@ -7,7 +7,7 @@ libdri2_la_CFLAGS = \
 	-I$(top_srcdir)/hw/xfree86/os-support/bus
 
 libdri2_la_LDFLAGS = -module -avoid-version $(LD_NO_UNDEFINED_FLAG)
-libdri2_la_LIBADD = @LIBDRM_LIBS@
+libdri2_la_LIBADD = @LIBDRM_LIBS@ $(PIXMAN_LIBS)
 libdri2_ladir = $(moduledir)/extensions
 libdri2_la_SOURCES = \
 	dri2.c \
diff --git a/xorg-server/hw/xfree86/i2c/Makefile.am b/xorg-server/hw/xfree86/i2c/Makefile.am
index f08541cf0..cb18db188 100644
--- a/xorg-server/hw/xfree86/i2c/Makefile.am
+++ b/xorg-server/hw/xfree86/i2c/Makefile.am
@@ -25,10 +25,7 @@ bt829_drv_la_LDFLAGS = -module -avoid-version $(LD_NO_UNDEFINED_FLAG)
 bt829_drv_la_SOURCES = bt829.c bt829.h bt829_module.c
 
 fi1236_drv_la_LDFLAGS = -module -avoid-version $(LD_NO_UNDEFINED_FLAG)
-fi1236_drv_la_SOURCES = fi1236.c fi1236.h fi1236_module.c
-if NO_UNDEFINED
-fi1236_drv_la_LIBADD = tda9885_drv.la
-endif
+fi1236_drv_la_SOURCES = fi1236.c fi1236.h fi1236_module.c tda9885.c
 
 msp3430_drv_la_LDFLAGS = -module -avoid-version $(LD_NO_UNDEFINED_FLAG)
 msp3430_drv_la_SOURCES = msp3430.c msp3430.h msp3430_module.c
diff --git a/xorg-server/hw/xfree86/loader/loader.c b/xorg-server/hw/xfree86/loader/loader.c
index b72b8b89d..edaefb8f9 100644
--- a/xorg-server/hw/xfree86/loader/loader.c
+++ b/xorg-server/hw/xfree86/loader/loader.c
@@ -163,7 +163,7 @@ LoaderSymbol(const char *name)
 void
 LoaderUnload(const char *name, void *handle)
 {
-    xf86Msg(X_INFO, "Unloading %s\n", name);
+    LogMessageVerbSigSafe(X_INFO, 1, "Unloading %s\n", name);
     if (handle)
         dlclose(handle);
 }
diff --git a/xorg-server/hw/xfree86/loader/loadmod.c b/xorg-server/hw/xfree86/loader/loadmod.c
index 706b9b3e8..72020a58c 100644
--- a/xorg-server/hw/xfree86/loader/loadmod.c
+++ b/xorg-server/hw/xfree86/loader/loadmod.c
@@ -1093,9 +1093,10 @@ UnloadModuleOrDriver(ModuleDescPtr mod)
         return;
 
     if (mod->parent)
-        xf86MsgVerb(X_INFO, 3, "UnloadSubModule: \"%s\"\n", mod->name);
+        LogMessageVerbSigSafe(X_INFO, 3, "UnloadSubModule: \"%s\"\n",
+                              mod->name);
     else
-        xf86MsgVerb(X_INFO, 3, "UnloadModule: \"%s\"\n", mod->name);
+        LogMessageVerbSigSafe(X_INFO, 3, "UnloadModule: \"%s\"\n", mod->name);
 
     if (mod->TearDownData != ModuleDuplicated) {
         if ((mod->TearDownProc) && (mod->TearDownData))
diff --git a/xorg-server/hw/xfree86/os-support/shared/sigio.c b/xorg-server/hw/xfree86/os-support/shared/sigio.c
index 12ae8a480..231d6c04f 100644
--- a/xorg-server/hw/xfree86/os-support/shared/sigio.c
+++ b/xorg-server/hw/xfree86/os-support/shared/sigio.c
@@ -99,6 +99,8 @@ xf86SIGIO(int sig)
     int save_errno = errno;     /* do not clobber the global errno */
     int r;
 
+    inSignalContext = TRUE;
+
     ready = xf86SigIOMask;
     to.tv_sec = 0;
     to.tv_usec = 0;
@@ -114,6 +116,8 @@ xf86SIGIO(int sig)
     }
     /* restore global errno */
     errno = save_errno;
+
+    inSignalContext = FALSE;
 }
 
 static int
diff --git a/xorg-server/hw/xfree86/xaa/Makefile.am b/xorg-server/hw/xfree86/xaa/Makefile.am
index f6480a713..5614d723a 100644
--- a/xorg-server/hw/xfree86/xaa/Makefile.am
+++ b/xorg-server/hw/xfree86/xaa/Makefile.am
@@ -11,8 +11,9 @@ POLYSEG = s-xaaLine.c s-xaaDashLine.c
 if XAA
 
 libxaa_la_LDFLAGS = -module -avoid-version $(LD_NO_UNDEFINED_FLAG)
+libxaa_la_LIBADD = $(PIXMAN_LIBS)
 if COMPOSITE
-libxaa_la_LIBADD = $(top_builddir)/miext/cw/libcw.la
+libxaa_la_LIBADD += $(top_builddir)/miext/cw/libcw.la
 endif
 
 module_LTLIBRARIES = libxaa.la
diff --git a/xorg-server/include/dixfont.h b/xorg-server/include/dixfont.h
index 9333041fb..3d09eb5ae 100644
--- a/xorg-server/include/dixfont.h
+++ b/xorg-server/include/dixfont.h
@@ -117,12 +117,13 @@ extern _X_EXPORT void FreeFonts(void);
 
 extern _X_EXPORT FontPtr find_old_font(XID /*id */ );
 
-extern _X_EXPORT void GetGlyphs(FontPtr /*font */ ,
-                                unsigned long /*count */ ,
-                                unsigned char * /*chars */ ,
-                                FontEncoding /*fontEncoding */ ,
-                                unsigned long * /*glyphcount */ ,
-                                CharInfoPtr * /*glyphs */ );
+#define GetGlyphs dixGetGlyphs
+extern _X_EXPORT void dixGetGlyphs(FontPtr /*font */ ,
+                                   unsigned long /*count */ ,
+                                   unsigned char * /*chars */ ,
+                                   FontEncoding /*fontEncoding */ ,
+                                   unsigned long * /*glyphcount */ ,
+                                   CharInfoPtr * /*glyphs */ );
 
 extern _X_EXPORT void QueryGlyphExtents(FontPtr /*pFont */ ,
                                         CharInfoPtr * /*charinfo */ ,
diff --git a/xorg-server/include/globals.h b/xorg-server/include/globals.h
index 8076955a9..6d3f3d708 100644
--- a/xorg-server/include/globals.h
+++ b/xorg-server/include/globals.h
@@ -2,6 +2,8 @@
 #ifndef _XSERV_GLOBAL_H_
 #define _XSERV_GLOBAL_H_
 
+#include <signal.h>
+
 #include "window.h"             /* for WindowPtr */
 
 /* Global X server variables that are visible to mi, dix, os, and ddx */
@@ -23,6 +25,7 @@ extern _X_EXPORT int GrabInProgress;
 extern _X_EXPORT Bool noTestExtensions;
 extern _X_EXPORT char *SeatId;
 extern _X_EXPORT char *ConnectionInfo;
+extern _X_EXPORT sig_atomic_t inSignalContext;
 
 #ifdef DPMSExtension
 extern _X_EXPORT CARD32 DPMSStandbyTime;
diff --git a/xorg-server/include/misc.h b/xorg-server/include/misc.h
index fea74b86c..aa62f6a3a 100644
--- a/xorg-server/include/misc.h
+++ b/xorg-server/include/misc.h
@@ -229,6 +229,8 @@ pad_to_int32(const int bytes)
 }
 
 extern char **xstrtokenize(const char *str, const char *separators);
+extern void FormatUInt64(uint64_t num, char *string);
+extern void FormatUInt64Hex(uint64_t num, char *string);
 
 /**
  * Compare the two version numbers comprising of major.minor.
@@ -369,10 +371,10 @@ extern _X_EXPORT unsigned long serverGeneration;
 /* Don't use this directly, use BUG_WARN or BUG_WARN_MSG instead */
 #define __BUG_WARN_MSG(cond, with_msg, ...)                                \
           do { if (cond) {                                                \
-              ErrorF("BUG: triggered 'if (" #cond ")'\n");                \
-              ErrorF("BUG: %s:%d in %s()\n",                              \
-                      __FILE__, __LINE__, __func__);                      \
-              if (with_msg) ErrorF(__VA_ARGS__);                          \
+              ErrorFSigSafe("BUG: triggered 'if (" #cond ")'\n");          \
+              ErrorFSigSafe("BUG: %s:%u in %s()\n",                        \
+                           __FILE__, __LINE__, __func__);                 \
+              if (with_msg) ErrorFSigSafe(__VA_ARGS__);                    \
               xorg_backtrace();                                           \
           } } while(0)
 
diff --git a/xorg-server/include/os.h b/xorg-server/include/os.h
index 276eb5213..e93c48ae6 100644
--- a/xorg-server/include/os.h
+++ b/xorg-server/include/os.h
@@ -49,6 +49,7 @@ SOFTWARE.
 
 #include "misc.h"
 #include <stdarg.h>
+#include <stdint.h>
 #include <string.h>
 
 #define SCREEN_SAVER_ON   0
@@ -604,6 +605,12 @@ _X_ATTRIBUTE_PRINTF(3, 4);
 extern _X_EXPORT void
 LogMessage(MessageType type, const char *format, ...)
 _X_ATTRIBUTE_PRINTF(2, 3);
+extern _X_EXPORT void
+LogMessageVerbSigSafe(MessageType type, int verb, const char *format, ...)
+_X_ATTRIBUTE_PRINTF(3, 4);
+extern _X_EXPORT void
+LogVMessageVerbSigSafe(MessageType type, int verb, const char *format, va_list args)
+_X_ATTRIBUTE_PRINTF(3, 0);
 
 extern _X_EXPORT void
 LogVHdrMessageVerb(MessageType type, int verb,
@@ -649,6 +656,12 @@ extern _X_EXPORT void
 ErrorF(const char *f, ...)
 _X_ATTRIBUTE_PRINTF(1, 2);
 extern _X_EXPORT void
+VErrorFSigSafe(const char *f, va_list args)
+_X_ATTRIBUTE_PRINTF(1, 0);
+extern _X_EXPORT void
+ErrorFSigSafe(const char *f, ...)
+_X_ATTRIBUTE_PRINTF(1, 2);
+extern _X_EXPORT void
 LogPrintMarkers(void);
 
 extern _X_EXPORT void
diff --git a/xorg-server/mi/mieq.c b/xorg-server/mi/mieq.c
index e117a8db7..b2c7769ec 100644
--- a/xorg-server/mi/mieq.c
+++ b/xorg-server/mi/mieq.c
@@ -276,23 +276,22 @@ mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e)
          */
         miEventQueue.dropped++;
         if (miEventQueue.dropped == 1) {
-            ErrorF
-                ("[mi] EQ overflowing.  Additional events will be discarded until existing events are processed.\n");
+            ErrorFSigSafe("[mi] EQ overflowing.  Additional events will be "
+                         "discarded until existing events are processed.\n");
             xorg_backtrace();
-            ErrorF
-                ("[mi] These backtraces from mieqEnqueue may point to a culprit higher up the stack.\n");
-            ErrorF("[mi] mieq is *NOT* the cause.  It is a victim.\n");
+            ErrorFSigSafe("[mi] These backtraces from mieqEnqueue may point to "
+                         "a culprit higher up the stack.\n");
+            ErrorFSigSafe("[mi] mieq is *NOT* the cause.  It is a victim.\n");
         }
         else if (miEventQueue.dropped % QUEUE_DROP_BACKTRACE_FREQUENCY == 0 &&
                  miEventQueue.dropped / QUEUE_DROP_BACKTRACE_FREQUENCY <=
                  QUEUE_DROP_BACKTRACE_MAX) {
-            ErrorF
-                ("[mi] EQ overflow continuing.  %lu events have been dropped.\n",
-                 miEventQueue.dropped);
+            ErrorFSigSafe("[mi] EQ overflow continuing.  %u events have been "
+                         "dropped.\n", miEventQueue.dropped);
             if (miEventQueue.dropped / QUEUE_DROP_BACKTRACE_FREQUENCY ==
                 QUEUE_DROP_BACKTRACE_MAX) {
-                ErrorF
-                    ("[mi] No further overflow reports will be reported until the clog is cleared.\n");
+                ErrorFSigSafe("[mi] No further overflow reports will be "
+                             "reported until the clog is cleared.\n");
             }
             xorg_backtrace();
         }
diff --git a/xorg-server/os/backtrace.c b/xorg-server/os/backtrace.c
index 81348f417..daac60cf6 100644
--- a/xorg-server/os/backtrace.c
+++ b/xorg-server/os/backtrace.c
@@ -45,29 +45,37 @@ xorg_backtrace(void)
     int size, i;
     Dl_info info;
 
-    ErrorF("\n");
-    ErrorF("Backtrace:\n");
+    ErrorFSigSafe("\n");
+    ErrorFSigSafe("Backtrace:\n");
     size = backtrace(array, 64);
     for (i = 0; i < size; i++) {
         int rc = dladdr(array[i], &info);
 
         if (rc == 0) {
-            ErrorF("%d: ?? [%p]\n", i, array[i]);
+            ErrorFSigSafe("%u: ?? [%p]\n", i, array[i]);
             continue;
         }
         mod = (info.dli_fname && *info.dli_fname) ? info.dli_fname : "(vdso)";
         if (info.dli_saddr)
-            ErrorF("%d: %s (%s+0x%lx) [%p]\n", i, mod,
-                   info.dli_sname,
-                   (long unsigned int) ((char *) array[i] -
-                                        (char *) info.dli_saddr), array[i]);
+            ErrorFSigSafe(
+                "%u: %s (%s+0x%x) [%p]\n",
+                i,
+                mod,
+                info.dli_sname,
+                (unsigned int)((char *) array[i] -
+                               (char *) info.dli_saddr),
+                array[i]);
         else
-            ErrorF("%d: %s (%p+0x%lx) [%p]\n", i, mod,
-                   info.dli_fbase,
-                   (long unsigned int) ((char *) array[i] -
-                                        (char *) info.dli_fbase), array[i]);
+            ErrorFSigSafe(
+                "%u: %s (%p+0x%x) [%p]\n",
+                i,
+                mod,
+                info.dli_fbase,
+                (unsigned int)((char *) array[i] -
+                               (char *) info.dli_fbase),
+                array[i]);
     }
-    ErrorF("\n");
+    ErrorFSigSafe("\n");
 }
 
 #else                           /* not glibc or glibc < 2.1 */
@@ -105,7 +113,7 @@ xorg_backtrace_frame(uintptr_t pc, int signo, void *arg)
             strcpy(signame, "unknown");
         }
 
-        ErrorF("** Signal %d (%s)\n", signo, signame);
+        ErrorFSigSafe("** Signal %u (%s)\n", signo, signame);
     }
 
     snprintf(header, sizeof(header), "%d: 0x%lx", depth, pc);
@@ -123,7 +131,8 @@ xorg_backtrace_frame(uintptr_t pc, int signo, void *arg)
             symname = "<section start>";
             offset = pc - (uintptr_t) dlinfo.dli_fbase;
         }
-        ErrorF("%s: %s:%s+0x%lx\n", header, dlinfo.dli_fname, symname, offset);
+        ErrorFSigSafe("%s: %s:%s+0x%x\n", header, dlinfo.dli_fname, symname,
+                     offset);
 
     }
     else {
@@ -131,7 +140,7 @@ xorg_backtrace_frame(uintptr_t pc, int signo, void *arg)
          * probably poke elfloader here, but haven't written that code yet,
          * so we just print the pc.
          */
-        ErrorF("%s\n", header);
+        ErrorFSigSafe("%s\n", header);
     }
 
     return 0;
@@ -183,7 +192,7 @@ xorg_backtrace_pstack(void)
 
             if (bytesread > 0) {
                 btline[bytesread] = 0;
-                ErrorF("%s", btline);
+                ErrorFSigSafe("%s", btline);
             }
             else if ((bytesread < 0) || ((errno != EINTR) && (errno != EAGAIN)))
                 done = 1;
@@ -203,8 +212,8 @@ void
 xorg_backtrace(void)
 {
 
-    ErrorF("\n");
-    ErrorF("Backtrace:\n");
+    ErrorFSigSafe("\n");
+    ErrorFSigSafe("Backtrace:\n");
 
 #ifdef HAVE_PSTACK
 /* First try fork/exec of pstack - otherwise fall back to walkcontext
@@ -221,9 +230,9 @@ xorg_backtrace(void)
             walkcontext(&u, xorg_backtrace_frame, &depth);
         else
 #endif
-            ErrorF("Failed to get backtrace info: %s\n", strerror(errno));
+            ErrorFSigSafe("Failed to get backtrace info: %s\n", strerror(errno));
     }
-    ErrorF("\n");
+    ErrorFSigSafe("\n");
 }
 
 #else
diff --git a/xorg-server/os/log.c b/xorg-server/os/log.c
index 2c13c1a7d..25da9f63a 100644
--- a/xorg-server/os/log.c
+++ b/xorg-server/os/log.c
@@ -108,6 +108,7 @@ void (*OsVendorVErrorFProc) (const char *, va_list args) = NULL;
 #endif
 
 static FILE *logFile = NULL;
+static int logFileFd = -1;
 static Bool logFlush = FALSE;
 static Bool logSync = FALSE;
 static int logVerbosity = DEFAULT_LOG_VERBOSITY;
@@ -171,6 +172,14 @@ asm(".desc ___crashreporter_info__, 0x10");
 #define X_NONE_STRING			""
 #endif
 
+static size_t
+strlen_sigsafe(const char *s)
+{
+    size_t len;
+    for (len = 0; s[len]; len++);
+    return len;
+}
+
 /*
  * LogInit is called to start logging to a file.  It is also called (with
  * NULL arguments) when logging to a file is not wanted.  It must always be
@@ -211,6 +220,8 @@ LogInit(const char *fname, const char *backup)
             FatalError("Cannot open log file \"%s\"\n", logFileName);
         setvbuf(logFile, NULL, _IONBF, 0);
 
+        logFileFd = fileno(logFile);
+
         /* Flush saved log information. */
         if (saveBuffer && bufferSize > 0) {
             fwrite(saveBuffer, bufferPos, 1, logFile);
@@ -243,6 +254,7 @@ LogClose(enum ExitCode error)
                (error == EXIT_NO_ERROR) ? "successfully" : "with error", error);
         fclose(logFile);
         logFile = NULL;
+        logFileFd = -1;
     }
 }
 
@@ -267,16 +279,97 @@ LogSetParameter(LogParameter param, int value)
     }
 }
 
-/* This function does the actual log message writes. */
+static int
+pnprintf(char *string, size_t size, const char *f, va_list args)
+{
+    int f_idx = 0;
+    int s_idx = 0;
+    int f_len = strlen_sigsafe(f);
+    char *string_arg;
+    char number[21];
+    int p_len;
+    int i;
+    uint64_t ui;
+
+    for (; f_idx < f_len && s_idx < size - 1; f_idx++) {
+        if (f[f_idx] != '%') {
+            string[s_idx++] = f[f_idx];
+            continue;
+        }
+
+        switch (f[++f_idx]) {
+        case 's':
+            string_arg = va_arg(args, char*);
+            p_len = strlen_sigsafe(string_arg);
+
+            for (i = 0; i < p_len && s_idx < size - 1; i++)
+                string[s_idx++] = string_arg[i];
+            break;
+
+        case 'u':
+            ui = va_arg(args, unsigned);
+            FormatUInt64(ui, number);
+            p_len = strlen_sigsafe(number);
+
+            for (i = 0; i < p_len && s_idx < size - 1; i++)
+                string[s_idx++] = number[i];
+            break;
+
+        case 'p':
+            string[s_idx++] = '0';
+            if (s_idx < size - 1)
+                string[s_idx++] = 'x';
+            ui = (uintptr_t)va_arg(args, void*);
+            FormatUInt64Hex(ui, number);
+            p_len = strlen_sigsafe(number);
+
+            for (i = 0; i < p_len && s_idx < size - 1; i++)
+                string[s_idx++] = number[i];
+            break;
+
+        case 'x':
+            ui = va_arg(args, unsigned);
+            FormatUInt64Hex(ui, number);
+            p_len = strlen_sigsafe(number);
+
+            for (i = 0; i < p_len && s_idx < size - 1; i++)
+                string[s_idx++] = number[i];
+            break;
+
+        default:
+            va_arg(args, char*);
+            string[s_idx++] = '%';
+            if (s_idx < size - 1)
+                string[s_idx++] = f[f_idx];
+            break;
+        }
+    }
+
+    string[s_idx] = '\0';
+
+    return s_idx;
+}
+
+/* This function does the actual log message writes. It must be signal safe.
+ * When attempting to call non-signal-safe functions, guard them with a check
+ * of the inSignalContext global variable. */
 static void
 LogSWrite(int verb, const char *buf, size_t len, Bool end_line)
 {
     static Bool newline = TRUE;
 
     if (verb < 0 || logVerbosity >= verb)
-        fwrite(buf, len, 1, stderr);
+        write(2, buf, len);
+
     if (verb < 0 || logFileVerbosity >= verb) {
-        if (logFile) {
+        if (inSignalContext && logFileFd >= 0) {
+            write(logFileFd, buf, len);
+#ifdef WIN32
+            if (logFlush && logSync)
+                fsync(logFileFd);
+#endif
+        }
+        else if (!inSignalContext && logFile) {
             if (newline)
                 fprintf(logFile, "[%10.3f] ", GetTimeInMillis() / 1000.0);
             newline = end_line;
@@ -289,7 +382,7 @@ LogSWrite(int verb, const char *buf, size_t len, Bool end_line)
 #endif
             }
         }
-        else if (needBuffer) {
+        else if (!inSignalContext && needBuffer) {
             if (len > bufferUnused) {
                 bufferSize += 1024;
                 bufferUnused += 1024;
@@ -370,6 +463,16 @@ LogVMessageVerb(MessageType type, int verb, const char *format, va_list args)
     Bool newline;
     size_t len = 0;
 
+    if (inSignalContext) {
+        BUG_WARN_MSG(inSignalContext,
+                     "Warning: attempting to log data in a signal unsafe "
+                     "manner while in signal context. Please update to check "
+                     "inSignalContext and/or use LogMessageVerbSigSafe() or "
+                     "ErrorFSigSafe(). The offending log format message is:\n"
+                     "%s\n", format);
+        return;
+    }
+
     type_str = LogMessageTypeVerbString(type, verb);
     if (!type_str)
         return;
@@ -411,6 +514,44 @@ LogMessage(MessageType type, const char *format, ...)
     va_end(ap);
 }
 
+/* Log a message using only signal safe functions. */
+void
+LogMessageVerbSigSafe(MessageType type, int verb, const char *format, ...)
+{
+    va_list ap;
+    va_start(ap, format);
+    LogVMessageVerbSigSafe(type, verb, format, ap);
+    va_end(ap);
+}
+
+void
+LogVMessageVerbSigSafe(MessageType type, int verb, const char *format, va_list args)
+{
+    const char *type_str;
+    char buf[1024];
+    int len;
+    Bool newline;
+
+    type_str = LogMessageTypeVerbString(type, verb);
+    if (!type_str)
+        return;
+
+    /* if type_str is not "", prepend it and ' ', to message */
+    if (type_str[0] != '\0') {
+        LogSWrite(verb, type_str, strlen_sigsafe(type_str), FALSE);
+        LogSWrite(verb, " ", 1, FALSE);
+    }
+
+    len = pnprintf(buf, sizeof(buf), format, args);
+
+    /* Force '\n' at end of truncated line */
+    if (sizeof(buf) - len == 1)
+        buf[len - 1] = '\n';
+
+    newline = (buf[len - 1] == '\n');
+    LogSWrite(verb, buf, len, newline);
+}
+
 void
 LogVHdrMessageVerb(MessageType type, int verb, const char *msg_format,
                    va_list msg_args, const char *hdr_format, va_list hdr_args)
@@ -421,6 +562,16 @@ LogVHdrMessageVerb(MessageType type, int verb, const char *msg_format,
     Bool newline;
     size_t len = 0;
 
+    if (inSignalContext) {
+        BUG_WARN_MSG(inSignalContext,
+                     "Warning: attempting to log data in a signal unsafe "
+                     "manner while in signal context. Please update to check "
+                     "inSignalContext and/or use LogMessageVerbSigSafe(). The "
+                     "offending header and log message formats are:\n%s %s\n",
+                     hdr_format, msg_format);
+        return;
+    }
+
     type_str = LogMessageTypeVerbString(type, verb);
     if (!type_str)
         return;
@@ -648,6 +799,22 @@ ErrorF(const char *f, ...)
     va_end(args);
 }
 
+void
+VErrorFSigSafe(const char *f, va_list args)
+{
+    LogVMessageVerbSigSafe(X_ERROR, -1, f, args);
+}
+
+void
+ErrorFSigSafe(const char *f, ...)
+{
+    va_list args;
+
+    va_start(args, f);
+    VErrorFSigSafe(f, args);
+    va_end(args);
+}
+
 void
 LogPrintMarkers(void)
 {
diff --git a/xorg-server/os/osinit.c b/xorg-server/os/osinit.c
index e2a220886..6cc040178 100644
--- a/xorg-server/os/osinit.c
+++ b/xorg-server/os/osinit.c
@@ -113,7 +113,7 @@ OsSigHandler(int signo)
     const char *dlerr = dlerror();
 
     if (dlerr) {
-        LogMessage(X_ERROR, "Dynamic loader error: %s\n", dlerr);
+        LogMessageVerbSigSafe(X_ERROR, 1, "Dynamic loader error: %s\n", dlerr);
     }
 #endif                          /* RTLD_DI_SETSIGNAL */
 
@@ -129,8 +129,8 @@ OsSigHandler(int signo)
 
 #ifdef SA_SIGINFO
     if (sip->si_code == SI_USER) {
-        ErrorF("Recieved signal %d sent by process %ld, uid %ld\n",
-               signo, (long) sip->si_pid, (long) sip->si_uid);
+        ErrorFSigSafe("Recieved signal %u sent by process %u, uid %u\n", signo,
+                     sip->si_pid, sip->si_uid);
     }
     else {
         switch (signo) {
@@ -138,7 +138,7 @@ OsSigHandler(int signo)
         case SIGBUS:
         case SIGILL:
         case SIGFPE:
-            ErrorF("%s at address %p\n", strsignal(signo), sip->si_addr);
+            ErrorFSigSafe("%s at address %p\n", strsignal(signo), sip->si_addr);
         }
     }
 #endif
diff --git a/xorg-server/os/utils.c b/xorg-server/os/utils.c
index 3a1ef9303..998c3ed4a 100644
--- a/xorg-server/os/utils.c
+++ b/xorg-server/os/utils.c
@@ -204,6 +204,8 @@ int auditTrailLevel = 1;
 
 char *SeatId = NULL;
 
+sig_atomic_t inSignalContext = FALSE;
+
 #if defined(SVR4) || defined(__linux__) || defined(CSRG_BASED)
 #define HAS_SAVED_IDS_AND_SETEUID
 #endif
@@ -1791,3 +1793,47 @@ xstrtokenize(const char *str, const char *separators)
     free(list);
     return NULL;
 }
+
+/* Format a number into a string in a signal safe manner. The string should be
+ * at least 21 characters in order to handle all uint64_t values. */
+void
+FormatUInt64(uint64_t num, char *string)
+{
+    uint64_t divisor;
+    int len;
+    int i;
+
+    for (len = 1, divisor = 10;
+         len < 20 && num / divisor;
+         len++, divisor *= 10);
+
+    for (i = len, divisor = 1; i > 0; i--, divisor *= 10)
+        string[i - 1] = '0' + ((num / divisor) % 10);
+
+    string[len] = '\0';
+}
+
+/* Format a number into a hexadecimal string in a signal safe manner. The string
+ * should be at least 17 characters in order to handle all uint64_t values. */
+void
+FormatUInt64Hex(uint64_t num, char *string)
+{
+    uint64_t divisor;
+    int len;
+    int i;
+
+    for (len = 1, divisor = 0x10;
+         len < 16 && num / divisor;
+         len++, divisor *= 0x10);
+
+    for (i = len, divisor = 1; i > 0; i--, divisor *= 0x10) {
+        int val = (num / divisor) % 0x10;
+
+        if (val < 10)
+            string[i - 1] = '0' + val;
+        else
+            string[i - 1] = 'a' + val - 10;
+    }
+
+    string[len] = '\0';
+}
diff --git a/xorg-server/test/.gitignore b/xorg-server/test/.gitignore
index 23d4c8f4f..363d4b683 100644
--- a/xorg-server/test/.gitignore
+++ b/xorg-server/test/.gitignore
@@ -8,3 +8,4 @@ touch
 xfree86
 xkb
 xtest
+signal-logging
diff --git a/xorg-server/test/Makefile.am b/xorg-server/test/Makefile.am
index a5a2e5c2b..e5b25c97f 100644
--- a/xorg-server/test/Makefile.am
+++ b/xorg-server/test/Makefile.am
@@ -5,7 +5,7 @@ if XORG
 # Tests that require at least some DDX functions in order to fully link
 # For now, requires xf86 ddx, could be adjusted to use another
 SUBDIRS += xi2
-noinst_PROGRAMS += xkb input xtest misc fixes xfree86  hashtabletest
+noinst_PROGRAMS += xkb input xtest misc fixes xfree86 hashtabletest signal-logging
 endif
 check_LTLIBRARIES = libxservertest.la
 
@@ -36,6 +36,7 @@ misc_LDADD=$(TEST_LDADD)
 fixes_LDADD=$(TEST_LDADD)
 xfree86_LDADD=$(TEST_LDADD)
 touch_LDADD=$(TEST_LDADD)
+signal_logging_LDADD=$(TEST_LDADD)
 hashtabletest_LDADD=$(TEST_LDADD) $(top_srcdir)/Xext/hashtable.c
 
 libxservertest_la_LIBADD = $(XSERVER_LIBS)
diff --git a/xorg-server/test/signal-logging.c b/xorg-server/test/signal-logging.c
new file mode 100644
index 000000000..8aab0dd58
--- /dev/null
+++ b/xorg-server/test/signal-logging.c
@@ -0,0 +1,115 @@
+/**
+ * Copyright © 2012 Canonical, Ltd.
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a
+ *  copy of this software and associated documentation files (the "Software"),
+ *  to deal in the Software without restriction, including without limitation
+ *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ *  and/or sell copies of the Software, and to permit persons to whom the
+ *  Software is furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice (including the next
+ *  paragraph) shall be included in all copies or substantial portions of the
+ *  Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ *  DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdint.h>
+#include "assert.h"
+#include "misc.h"
+
+struct number_format_test {
+    uint64_t number;
+    char string[21];
+    char hex_string[17];
+};
+
+static Bool
+check_number_format_test(const struct number_format_test *test)
+{
+    char string[21];
+
+    FormatUInt64(test->number, string);
+    if(strncmp(string, test->string, 21) != 0) {
+        fprintf(stderr, "Failed to convert %ju to decimal string (%s vs %s)\n",
+                test->number, test->string, string);
+        return FALSE;
+    }
+    FormatUInt64Hex(test->number, string);
+    if(strncmp(string, test->hex_string, 17) != 0) {
+        fprintf(stderr,
+                "Failed to convert %ju to hexadecimal string (%s vs %s)\n",
+                test->number, test->hex_string, string);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+static Bool
+number_formatting(void)
+{
+    int i;
+    struct number_format_test tests[] = {
+        { /* Zero */
+            0,
+            "0",
+            "0",
+        },
+        { /* Single digit number */
+            5,
+            "5",
+            "5",
+        },
+        { /* Two digit decimal number */
+            12,
+            "12",
+            "c",
+        },
+        { /* Two digit hex number */
+            37,
+            "37",
+            "25",
+        },
+        { /* Large < 32 bit number */
+            0xC90B2,
+            "823474",
+            "c90b2",
+        },
+        { /* Large > 32 bit number */
+            0x15D027BF211B37A,
+            "98237498237498234",
+            "15d027bf211b37a",
+        },
+        { /* Maximum 64-bit number */
+            0xFFFFFFFFFFFFFFFF,
+            "18446744073709551615",
+            "ffffffffffffffff",
+        },
+    };
+
+    for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
+        if (!check_number_format_test(tests + i))
+            return FALSE;
+
+    return TRUE;
+}
+
+int
+main(int argc, char **argv)
+{
+    int ok = number_formatting();
+
+    return ok ? 0 : 1;
+}
-- 
cgit v1.2.3