diff options
Diffstat (limited to 'xorg-server')
27 files changed, 467 insertions, 77 deletions
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; @@ -649,6 +800,22 @@ ErrorF(const char *f, ...) } 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) { /* Show what the message marker symbols mean. */ 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; +} |