[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH 5/6] Add an an internal API for emergency dump of debug buffer



virLogEmergencyDumpAll() allows to dump the content of the
debug buffer from within a signal handler. It saves to all
log file or stderr if none is found
* src/util/logging.h src/util/logging.c: add the new API
  and cleanup the old virLogDump code
* src/libvirt_private.syms: exports it as a private symbol

Signed-off-by: Daniel Veillard <veillard redhat com>
---
 src/libvirt_private.syms |    1 +
 src/util/logging.c       |   87 +++++++++++++++++++++++++++------------------
 src/util/logging.h       |    2 +-
 3 files changed, 54 insertions(+), 36 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 5e63a12..7c4b33a 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 b946285..98e175e 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,64 @@ 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));
+        }
+    }
+    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 2e2734e..c168dff 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

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]