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 <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,
|
||||
|
|
135
os/log.c
135
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,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;
|
||||
|
@ -293,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;
|
||||
|
@ -415,6 +504,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)
|
||||
|
|
Loading…
Reference in New Issue