In case of imminent crash or upon request (signal USR2),
dump the logging buffer to the libvirtd.log file for
post-mortem analysis
* daemon/libvirtd.c: create a sig_fatal() handler connected to
  SIGFPE SIGSEGV SIGILL SIGABRT SIGBUS and SIGUSR2, just dumping
  the log buffer to the libvirtd.log open file descriptor

Signed-off-by: Daniel Veillard <veill...@redhat.com>
---
 daemon/libvirtd.c |   51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 51 insertions(+), 0 deletions(-)

diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index 42e8585..3338336 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -248,6 +248,45 @@ static void sig_handler(int sig, siginfo_t * siginfo,
     errno = origerrno;
 }
 
+static int sig_fatal_dump(void *data ATTRIBUTE_UNUSED,
+                          const char *buf, int len) {
+   int r;
+
+   r = safewrite(logFD, buf, len);
+   return(r);
+}
+
+static void sig_fatal(int sig, siginfo_t * siginfo ATTRIBUTE_UNUSED,
+                      void* context ATTRIBUTE_UNUSED) {
+    struct sigaction sig_action;
+    int origerrno;
+    int r;
+    char buf[100];
+
+    origerrno = errno;
+    snprintf(buf, sizeof(buf) - 1,
+             "Caught signal %d, dumping internal log buffer:\n", sig);
+    buf[sizeof(buf) - 1] = 0;
+    r = safewrite(logFD, buf, strlen(buf));
+    snprintf(buf, sizeof(buf) - 1, "\n\n    ====== start of log =====\n\n");
+    r = safewrite(logFD, buf, strlen(buf));
+    virLogDump(NULL, sig_fatal_dump);
+    snprintf(buf, sizeof(buf) - 1, "\n\n     ====== end of log =====\n\n");
+    r = safewrite(logFD, buf, strlen(buf));
+    fsync(logFD);
+
+    /*
+     * If the signal is fatal, avoid looping over this handler
+     * by desactivating it
+     */
+    if (sig != SIGUSR2) {
+        sig_action.sa_flags = SA_SIGINFO;
+        sig_action.sa_handler = SIG_IGN;
+        sigaction(sig, &sig_action, NULL);
+    }
+    errno = origerrno;
+}
+
 static void qemudDispatchClientEvent(int watch, int fd, int events, void *opaque);
 static void qemudDispatchServerEvent(int watch, int fd, int events, void *opaque);
 static int qemudStartWorker(struct qemud_server *server, struct qemud_worker *worker);
@@ -3099,6 +3138,18 @@ daemonSetupSignals(struct qemud_server *server)
     sigaction(SIGQUIT, &sig_action, NULL);
     sigaction(SIGTERM, &sig_action, NULL);
 
+    /*
+     * catch fatal errors to dump a log, also hook to USR2 for dynamic
+     * debugging purposes or testing
+     */
+    sig_action.sa_sigaction = sig_fatal;
+    sigaction(SIGFPE, &sig_action, NULL);
+    sigaction(SIGSEGV, &sig_action, NULL);
+    sigaction(SIGILL, &sig_action, NULL);
+    sigaction(SIGABRT, &sig_action, NULL);
+    sigaction(SIGBUS, &sig_action, NULL);
+    sigaction(SIGUSR2, &sig_action, NULL);
+
     sig_action.sa_handler = SIG_IGN;
     sigaction(SIGPIPE, &sig_action, NULL);
 
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to