43fe83
From d1105a7417a983af1cc6fa4ea6a0657fa6413481 Mon Sep 17 00:00:00 2001
43fe83
Message-Id: <d1105a7417a983af1cc6fa4ea6a0657fa6413481.1382534060.git.jdenemar@redhat.com>
43fe83
From: Peter Krempa <pkrempa@redhat.com>
43fe83
Date: Thu, 10 Oct 2013 13:56:31 +0200
43fe83
Subject: [PATCH] qemu: monitor: Produce better errors on monitor hangup
43fe83
43fe83
https://bugzilla.redhat.com/show_bug.cgi?id=1001738
43fe83
43fe83
Change the monitor error code to add the ability to access the qemu log
43fe83
file using a file descriptor so that we can dig in it for a more useful
43fe83
error message. The error is now logged on monitor hangups and overwrites
43fe83
a possible lesser error. A hangup on the monitor usualy means that qemu
43fe83
has crashed and there's a significant chance it produced a useful error
43fe83
message.
43fe83
43fe83
The functionality will be latent until the next patch.
43fe83
43fe83
(cherry picked from commit 90139a6236eb20a5cd2595af39ea11adae7d54de)
43fe83
43fe83
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
43fe83
---
43fe83
 src/qemu/qemu_monitor.c | 66 ++++++++++++++++++++++++++++++++++++++++++++-----
43fe83
 1 file changed, 60 insertions(+), 6 deletions(-)
43fe83
43fe83
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
43fe83
index 2eb536c..cf4f954 100644
43fe83
--- a/src/qemu/qemu_monitor.c
43fe83
+++ b/src/qemu/qemu_monitor.c
43fe83
@@ -32,6 +32,8 @@
43fe83
 #include "qemu_monitor.h"
43fe83
 #include "qemu_monitor_text.h"
43fe83
 #include "qemu_monitor_json.h"
43fe83
+#include "qemu_domain.h"
43fe83
+#include "qemu_process.h"
43fe83
 #include "virerror.h"
43fe83
 #include "viralloc.h"
43fe83
 #include "virlog.h"
43fe83
@@ -332,6 +334,35 @@ qemuMonitorOpenPty(const char *monitor)
43fe83
 }
43fe83
 
43fe83
 
43fe83
+/* Get a possible error from qemu's log. This function closes the
43fe83
+ * corresponding log fd */
43fe83
+static char *
43fe83
+qemuMonitorGetErrorFromLog(qemuMonitorPtr mon)
43fe83
+{
43fe83
+    int len;
43fe83
+    char *logbuf = NULL;
43fe83
+    int orig_errno = errno;
43fe83
+
43fe83
+    if (mon->logfd < 0)
43fe83
+        return NULL;
43fe83
+
43fe83
+    if (VIR_ALLOC_N_QUIET(logbuf, 4096) < 0)
43fe83
+        goto error;
43fe83
+
43fe83
+    if ((len = qemuProcessReadLog(mon->logfd, logbuf, 4096 - 1, 0, true)) <= 0)
43fe83
+        goto error;
43fe83
+
43fe83
+cleanup:
43fe83
+    errno = orig_errno;
43fe83
+    VIR_FORCE_CLOSE(mon->logfd);
43fe83
+    return logbuf;
43fe83
+
43fe83
+error:
43fe83
+    VIR_FREE(logbuf);
43fe83
+    goto cleanup;
43fe83
+}
43fe83
+
43fe83
+
43fe83
 /* This method processes data that has been received
43fe83
  * from the monitor. Looking for async events and
43fe83
  * replies/errors.
43fe83
@@ -565,6 +596,7 @@ qemuMonitorIO(int watch, int fd, int events, void *opaque) {
43fe83
     qemuMonitorPtr mon = opaque;
43fe83
     bool error = false;
43fe83
     bool eof = false;
43fe83
+    bool hangup = false;
43fe83
 
43fe83
     virObjectRef(mon);
43fe83
 
43fe83
@@ -615,12 +647,14 @@ qemuMonitorIO(int watch, int fd, int events, void *opaque) {
43fe83
             }
43fe83
         }
43fe83
 
43fe83
-        if (!error &&
43fe83
-            events & VIR_EVENT_HANDLE_HANGUP) {
43fe83
-            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
43fe83
-                           _("End of file from monitor"));
43fe83
-            eof = true;
43fe83
-            events &= ~VIR_EVENT_HANDLE_HANGUP;
43fe83
+        if (events & VIR_EVENT_HANDLE_HANGUP) {
43fe83
+            hangup = true;
43fe83
+            if (!error) {
43fe83
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
43fe83
+                               _("End of file from monitor"));
43fe83
+                eof = true;
43fe83
+                events &= ~VIR_EVENT_HANDLE_HANGUP;
43fe83
+            }
43fe83
         }
43fe83
 
43fe83
         if (!error && !eof &&
43fe83
@@ -639,6 +673,26 @@ qemuMonitorIO(int watch, int fd, int events, void *opaque) {
43fe83
     }
43fe83
 
43fe83
     if (error || eof) {
43fe83
+        if (hangup) {
43fe83
+            /* Check if an error message from qemu is available and if so, use
43fe83
+             * it to overwrite the actual message. It's done only in early
43fe83
+             * startup phases where the message from qemu is certainly more
43fe83
+             * interesting than a "connection reset by peer" message.
43fe83
+             */
43fe83
+            char *qemuMessage;
43fe83
+
43fe83
+            if ((qemuMessage = qemuMonitorGetErrorFromLog(mon))) {
43fe83
+                virReportError(VIR_ERR_INTERNAL_ERROR,
43fe83
+                               _("early end of file from monitor: "
43fe83
+                                 "possible problem:\n%s"),
43fe83
+                               qemuMessage);
43fe83
+                virCopyLastError(&mon->lastError);
43fe83
+                virResetLastError();
43fe83
+            }
43fe83
+
43fe83
+            VIR_FREE(qemuMessage);
43fe83
+        }
43fe83
+
43fe83
         if (mon->lastError.code != VIR_ERR_OK) {
43fe83
             /* Already have an error, so clear any new error */
43fe83
             virResetLastError();
43fe83
-- 
43fe83
1.8.4
43fe83