On Mon, May 14, 2012 at 02:14:26PM -0700, Chase Douglas wrote: > Signed-off-by: Chase Douglas <[email protected]> > --- > Changes since v3: > * Rebased onto master > - Log writing now occurs in LogSWrite, which is now signal-safe > * Removed timestamp logging, it's not safe to get the current timestamp
tempted to have this added again with the required MONOTONIC_CLOCK defines defines, the timestamps would be useful to have. follow up patch though. A rather cross-eyed Reviewed-by: Peter Hutterer <[email protected]> for the series. Cheers, Peter > * Updated pnprintf to use 21 character string for number formats > > include/os.h | 54 ++++++++++++++++++++++++++ > os/log.c | 120 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- > 2 files changed, 170 insertions(+), 4 deletions(-) > > diff --git a/include/os.h b/include/os.h > index 276eb52..8e7aedb 100644 > --- a/include/os.h > +++ b/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 > @@ -583,6 +584,8 @@ typedef enum { > X_UNKNOWN = -1 /* unknown -- this must always be last */ > } MessageType; > > +typedef const uint64_t log_param_t; > + > extern _X_EXPORT const char * > LogInit(const char *fname, const char *backup); > extern _X_EXPORT void > @@ -604,6 +607,9 @@ _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, > + const log_param_t *args, int num_args); > > extern _X_EXPORT void > LogVHdrMessageVerb(MessageType type, int verb, > @@ -654,4 +660,52 @@ LogPrintMarkers(void); > extern _X_EXPORT void > xorg_backtrace(void); > > +#define NARG(...) (NARG_(__VA_ARGS__, RSEQ_N) - (sizeof(#__VA_ARGS__) == 1)) > +#define NARG_(...) NARG__(__VA_ARGS__) > +#define NARG__( _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) (N) > +#define RSEQ_N 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 > + > +#define ARG_N_9_(_1, _2, _3, _4, _5, _6, _7, _8, _9, N, ...) (log_param_t)(N) > +#define ARG_N_9(...) ARG_N_9_(__VA_ARGS__) > +#define ARG_N_8_(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) (log_param_t)(N) > +#define ARG_N_8(...) ARG_N_8_(__VA_ARGS__) > +#define ARG_N_7_(_1, _2, _3, _4, _5, _6, _7, N, ...) (log_param_t)(N) > +#define ARG_N_7(...) ARG_N_7_(__VA_ARGS__) > +#define ARG_N_6_(_1, _2, _3, _4, _5, _6, N, ...) (log_param_t)(N) > +#define ARG_N_6(...) ARG_N_6_(__VA_ARGS__) > +#define ARG_N_5_(_1, _2, _3, _4, _5, N, ...) (log_param_t)(N) > +#define ARG_N_5(...) ARG_N_5_(__VA_ARGS__) > +#define ARG_N_4_(_1, _2, _3, _4, N, ...) (log_param_t)(N) > +#define ARG_N_4(...) ARG_N_4_(__VA_ARGS__) > +#define ARG_N_3_(_1, _2, _3, N, ...) (log_param_t)(N) > +#define ARG_N_3(...) ARG_N_3_(__VA_ARGS__) > +#define ARG_N_2_(_1, _2, N, ...) (log_param_t)(N) > +#define ARG_N_2(...) ARG_N_2_(__VA_ARGS__) > +#define ARG_N_1_(_1, N, ...) (log_param_t)(N) > +#define ARG_N_1(...) ARG_N_1_(__VA_ARGS__) > +#define ARG_N_0(N, ...) (log_param_t)(sizeof(#N) != 1 ? N : 0) > + > +/* Only 10 arguments are supported. If more are needed, update the NARG__, > + * RSEQ_N, and ARG_N_* macros. */ > +#define LogMessageVerbSigSafe(type, verb, fmt, ...) do { \ > + int _num_args = NARG(__VA_ARGS__); \ > + uint64_t _args[_num_args]; \ > +_Pragma("GCC diagnostic push") \ > +_Pragma("GCC diagnostic ignored \"-Wbad-function-cast\"") \ > + switch (_num_args) { \ > + case 10: _args[9] = ARG_N_9(__VA_ARGS__, RSEQ_N); \ > + case 9: _args[8] = ARG_N_8(__VA_ARGS__, RSEQ_N); \ > + case 8: _args[7] = ARG_N_7(__VA_ARGS__, RSEQ_N); \ > + case 7: _args[6] = ARG_N_6(__VA_ARGS__, RSEQ_N); \ > + case 6: _args[5] = ARG_N_5(__VA_ARGS__, RSEQ_N); \ > + case 5: _args[4] = ARG_N_4(__VA_ARGS__, RSEQ_N); \ > + case 4: _args[3] = ARG_N_3(__VA_ARGS__, RSEQ_N); \ > + case 3: _args[2] = ARG_N_2(__VA_ARGS__, RSEQ_N); \ > + case 2: _args[1] = ARG_N_1(__VA_ARGS__, RSEQ_N); \ > + case 1: _args[0] = ARG_N_0(__VA_ARGS__, RSEQ_N); \ > + } \ > +_Pragma("GCC diagnostic pop") \ > + _LogMessageVerbSigSafe(type, verb, fmt, _args, _num_args); \ > +} while(0) > + > #endif /* OS_H */ > diff --git a/os/log.c b/os/log.c > index 5394847..8adf6cc 100644 > --- a/os/log.c > +++ b/os/log.c > @@ -172,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 > @@ -271,16 +279,90 @@ LogSetParameter(LogParameter param, int value) > } > } > > -/* This function does the actual log message writes. */ > +static int > +pnprintf(char *string, size_t size, const char *f, log_param_t *args, > + int num_args) > +{ > + int f_idx = 0; > + int s_idx = 0; > + int p_idx = 0; > + int f_len = strlen_sigsafe(f); > + char *string_arg; > + char number[21]; > + int p_len; > + int i; > + > + for (; f_idx < f_len && s_idx < size - 1; f_idx++) { > + if (f[f_idx] != '%' || p_idx >= num_args) { > + string[s_idx++] = f[f_idx]; > + continue; > + } > + > + switch (f[++f_idx]) { > + case 's': > + string_arg = (char *)args[p_idx++]; > + 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': > + FormatUInt64((uint64_t)args[p_idx++], 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'; > + /* Intentional fall-through */ > + > + case 'x': > + FormatUInt64Hex((uint64_t)args[p_idx++], number); > + p_len = strlen_sigsafe(number); > + > + for (i = 0; i < p_len && s_idx < size - 1; i++) > + string[s_idx++] = number[i]; > + break; > + > + default: > + p_idx++; > + 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; > @@ -293,7 +375,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; > @@ -415,6 +497,36 @@ 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, > + const log_param_t *args, int num_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, num_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) > -- > 1.7.9.5 > _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
