Add LogMessageVerbSigSafe() for logging messages while in signal context
[whot: edited to use varargs, squashed commit below] Signed-off-by: Chase Douglas <chase.douglas@canonical.com> Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net> Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> os: fix vararg length calculation Make %u and %x sizeof(unsigned int), %p sizeof(void*). This is printf behaviour and we can't guarantee that void* is uint64_t anyway. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Chase Douglas <chase.douglas@canonical.com>
This commit is contained in:
parent
704b847abf
commit
164b38c72f
|
@ -49,6 +49,7 @@ SOFTWARE.
|
||||||
|
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#define SCREEN_SAVER_ON 0
|
#define SCREEN_SAVER_ON 0
|
||||||
|
@ -604,6 +605,12 @@ _X_ATTRIBUTE_PRINTF(3, 4);
|
||||||
extern _X_EXPORT void
|
extern _X_EXPORT void
|
||||||
LogMessage(MessageType type, const char *format, ...)
|
LogMessage(MessageType type, const char *format, ...)
|
||||||
_X_ATTRIBUTE_PRINTF(2, 3);
|
_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
|
extern _X_EXPORT void
|
||||||
LogVHdrMessageVerb(MessageType type, int verb,
|
LogVHdrMessageVerb(MessageType type, int verb,
|
||||||
|
|
135
os/log.c
135
os/log.c
|
@ -172,6 +172,14 @@ asm(".desc ___crashreporter_info__, 0x10");
|
||||||
#define X_NONE_STRING ""
|
#define X_NONE_STRING ""
|
||||||
#endif
|
#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
|
* 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
|
* NULL arguments) when logging to a file is not wanted. It must always be
|
||||||
|
@ -271,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
|
static void
|
||||||
LogSWrite(int verb, const char *buf, size_t len, Bool end_line)
|
LogSWrite(int verb, const char *buf, size_t len, Bool end_line)
|
||||||
{
|
{
|
||||||
static Bool newline = TRUE;
|
static Bool newline = TRUE;
|
||||||
|
|
||||||
if (verb < 0 || logVerbosity >= verb)
|
if (verb < 0 || logVerbosity >= verb)
|
||||||
fwrite(buf, len, 1, stderr);
|
write(2, buf, len);
|
||||||
|
|
||||||
if (verb < 0 || logFileVerbosity >= verb) {
|
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)
|
if (newline)
|
||||||
fprintf(logFile, "[%10.3f] ", GetTimeInMillis() / 1000.0);
|
fprintf(logFile, "[%10.3f] ", GetTimeInMillis() / 1000.0);
|
||||||
newline = end_line;
|
newline = end_line;
|
||||||
|
@ -293,7 +382,7 @@ LogSWrite(int verb, const char *buf, size_t len, Bool end_line)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (needBuffer) {
|
else if (!inSignalContext && needBuffer) {
|
||||||
if (len > bufferUnused) {
|
if (len > bufferUnused) {
|
||||||
bufferSize += 1024;
|
bufferSize += 1024;
|
||||||
bufferUnused += 1024;
|
bufferUnused += 1024;
|
||||||
|
@ -415,6 +504,44 @@ LogMessage(MessageType type, const char *format, ...)
|
||||||
va_end(ap);
|
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
|
void
|
||||||
LogVHdrMessageVerb(MessageType type, int verb, const char *msg_format,
|
LogVHdrMessageVerb(MessageType type, int verb, const char *msg_format,
|
||||||
va_list msg_args, const char *hdr_format, va_list hdr_args)
|
va_list msg_args, const char *hdr_format, va_list hdr_args)
|
||||||
|
|
Loading…
Reference in New Issue