diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 5e63a128035e6ee4084906bf8d4277caf7359fc0..7c4b33a2f86c34b46efbb937679812d6210a558c 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -541,6 +541,7 @@ virRegisterStorageDriver; # logging.h virLogDefineFilter; virLogDefineOutput; +virLogEmergencyDumpAll; virLogGetDefaultPriority; virLogGetFilters; virLogGetNbFilters; diff --git a/src/util/logging.c b/src/util/logging.c index b946285ea1c4cb492006ea9f155a81b2bfb9458b..e39e6c5dc5d2cc97e728ede0a14d85e624d144c0 100644 --- a/src/util/logging.c +++ b/src/util/logging.c @@ -129,6 +129,9 @@ static virLogPriority virLogDefaultPriority = VIR_LOG_DEFAULT; static int virLogResetFilters(void); static int virLogResetOutputs(void); +static int virLogOutputToFd(const char *category, int priority, + const char *funcname, long long linenr, + const char *str, int len, void *data); /* * Logs accesses must be serialized though a mutex @@ -277,50 +280,66 @@ static void virLogStr(const char *str, int len) { virLogUnlock(); } -#if 0 -/* - * Output the ring buffer +static void virLogDumpAllFD(const char *msg, int len) { + int i, found = 0; + + for (i = 0; i < virLogNbOutputs;i++) { + if (virLogOutputs[i].f == virLogOutputToFd) { + int fd = (long) virLogOutputs[i].data; + + if (fd >= 0) { + ignore_value (safewrite(fd, msg, len)); + found = 1; + } + } + } + if (!found) + ignore_value (safewrite(STDERR_FILENO, msg, len)); +} + +/** + * virLogEmergencyDumpAll: + * @signum: the signal number + * + * Emergency function called, possibly from a signal handler. + * It need to output the debug ring buffer through the log + * output which are safe to use from a signal handler. + * In case none is found it is emitted to standard error. */ -static int virLogDump(void *data, virLogOutputFunc f) { - int ret = 0, tmp; +void +virLogEmergencyDumpAll(int signum) { + int ret = 0, len; + char buf[100]; + + if (virLogLen == 0) + return; - if ((virLogLen == 0) || (f == NULL)) - return 0; virLogLock(); - if (virLogStart + virLogLen < LOG_BUFFER_SIZE) { -push_end: - virLogBuffer[virLogStart + virLogLen] = 0; - tmp = f(data, &virLogBuffer[virLogStart], virLogLen); - if (tmp < 0) { - ret = -1; - goto error; - } - ret += tmp; - virLogStart += tmp; - virLogLen -= tmp; - } else { - tmp = LOG_BUFFER_SIZE - virLogStart; - ret = f(data, &virLogBuffer[virLogStart], tmp); - if (ret < 0) { - ret = -1; - goto error; - } - if (ret < tmp) { - virLogStart += ret; - virLogLen -= ret; + snprintf(buf, sizeof(buf) - 1, + "Caught signal %d, dumping internal log buffer:\n", signum); + buf[sizeof(buf) - 1] = 0; + virLogDumpAllFD(buf, strlen(buf)); + snprintf(buf, sizeof(buf) - 1, "\n\n ====== start of log =====\n\n"); + virLogDumpAllFD(buf, strlen(buf)); + while (virLogLen > 0) { + if (virLogStart + virLogLen < LOG_BUFFER_SIZE) { + virLogBuffer[virLogStart + virLogLen] = 0; + virLogDumpAllFD(&virLogBuffer[virLogStart], virLogLen); + ret += virLogLen; + virLogStart += virLogLen; + virLogLen = 0; } else { + len = LOG_BUFFER_SIZE - virLogStart; + virLogBuffer[LOG_BUFFER_SIZE] = 0; + virLogDumpAllFD(&virLogBuffer[virLogStart], len); + virLogLen -= len; virLogStart = 0; - virLogLen -= tmp; - /* dump the second part */ - if (virLogLen > 0) - goto push_end; } } -error: + snprintf(buf, sizeof(buf) - 1, "\n\n ====== end of log =====\n\n"); + virLogDumpAllFD(buf, strlen(buf)); virLogUnlock(); - return ret; } -#endif /** * virLogSetDefaultPriority: diff --git a/src/util/logging.h b/src/util/logging.h index 2e2734ed6506157e506f5d64e5ae8a73e4132a92..c168dff5c8c6b09efb91befbb0cc27d132cb4732 100644 --- a/src/util/logging.h +++ b/src/util/logging.h @@ -133,5 +133,5 @@ extern int virLogParseOutputs(const char *output); extern void virLogMessage(const char *category, int priority, const char *funcname, long long linenr, int flags, const char *fmt, ...) ATTRIBUTE_FMT_PRINTF(6, 7); - +extern void virLogEmergencyDumpAll(int signum); #endif