diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index c67fcb5dac..a655190f94 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -246,6 +246,26 @@ static void sig_handler(int sig, siginfo_t * siginfo,
     errno = origerrno;
 }
 
+static void sig_fatal(int sig, siginfo_t * siginfo ATTRIBUTE_UNUSED,
+                      void* context ATTRIBUTE_UNUSED) {
+    struct sigaction sig_action;
+    int origerrno;
+
+    origerrno = errno;
+    virLogEmergencyDumpAll(sig);
+
+    /*
+     * 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);
@@ -3046,6 +3066,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);