Merge branch 'sigsafe-logging-varargs'
This merge includes a minor fixup for '%p' arguments; must cast to uintptr_t instead of uint64_t as we use -Werror=pointer-to-int-cast which complains when doing a cast (even explicitly) from a pointer to an integer of different size.
This commit is contained in:
commit
24525d96a3
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
13
include/os.h
13
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
|
||||
|
|
19
mi/mieq.c
19
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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
175
os/log.c
175
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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
46
os/utils.c
46
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';
|
||||
}
|
||||
|
|
1
test/.gitignore
vendored
1
test/.gitignore
vendored
|
@ -8,3 +8,4 @@ touch
|
|||
xfree86
|
||||
xkb
|
||||
xtest
|
||||
signal-logging
|
||||
|
|
|
@ -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)
|
||||
|
|
115
test/signal-logging.c
Normal file
115
test/signal-logging.c
Normal file
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user