[PATCHv2 3/4] qemu: monitor: Produce better errors on monitor hangup

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

 



Change the monitor error code to add the ability to access the qemu log
file using a file descriptor so that we can dig in it for a more useful
error message. The error is now logged on monitor hangups and overwrites
a possible lesser error. A hangup on the monitor usualy means that qemu
has crashed and there's a significant chance it produced a useful error
message.

The functionality will be latent until the next patch.
---

Notes:
    Version 2:
    - fixed typos
    - avoided unnecessary reset of error
    - removed unneeded strlen to check returned log string

 src/qemu/qemu_monitor.c | 66 ++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 60 insertions(+), 6 deletions(-)

diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index c3701fe..a601ee0 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -32,6 +32,8 @@
 #include "qemu_monitor.h"
 #include "qemu_monitor_text.h"
 #include "qemu_monitor_json.h"
+#include "qemu_domain.h"
+#include "qemu_process.h"
 #include "virerror.h"
 #include "viralloc.h"
 #include "virlog.h"
@@ -331,6 +333,35 @@ qemuMonitorOpenPty(const char *monitor)
 }


+/* Get a possible error from qemu's log. This function closes the
+ * corresponding log fd */
+static char *
+qemuMonitorGetErrorFromLog(qemuMonitorPtr mon)
+{
+    int len;
+    char *logbuf = NULL;
+    int orig_errno = errno;
+
+    if (mon->logfd < 0)
+        return NULL;
+
+    if (VIR_ALLOC_N_QUIET(logbuf, 4096) < 0)
+        goto error;
+
+    if ((len = qemuProcessReadLog(mon->logfd, logbuf, 4096 - 1, 0, true)) <= 0)
+        goto error;
+
+cleanup:
+    errno = orig_errno;
+    VIR_FORCE_CLOSE(mon->logfd);
+    return logbuf;
+
+error:
+    VIR_FREE(logbuf);
+    goto cleanup;
+}
+
+
 /* This method processes data that has been received
  * from the monitor. Looking for async events and
  * replies/errors.
@@ -564,6 +595,7 @@ qemuMonitorIO(int watch, int fd, int events, void *opaque) {
     qemuMonitorPtr mon = opaque;
     bool error = false;
     bool eof = false;
+    bool hangup = false;

     virObjectRef(mon);

@@ -614,12 +646,14 @@ qemuMonitorIO(int watch, int fd, int events, void *opaque) {
             }
         }

-        if (!error &&
-            events & VIR_EVENT_HANDLE_HANGUP) {
-            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                           _("End of file from monitor"));
-            eof = true;
-            events &= ~VIR_EVENT_HANDLE_HANGUP;
+        if (events & VIR_EVENT_HANDLE_HANGUP) {
+            hangup = true;
+            if (!error) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("End of file from monitor"));
+                eof = true;
+                events &= ~VIR_EVENT_HANDLE_HANGUP;
+            }
         }

         if (!error && !eof &&
@@ -638,6 +672,26 @@ qemuMonitorIO(int watch, int fd, int events, void *opaque) {
     }

     if (error || eof) {
+        if (hangup) {
+            /* Check if an error message from qemu is available and if so, use
+             * it to overwrite the actual message. It's done only in early
+             * startup phases where the message from qemu is certainly more
+             * interesting than a "connection reset by peer" message.
+             */
+            char *qemuMessage;
+
+            if ((qemuMessage = qemuMonitorGetErrorFromLog(mon))) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("early end of file from monitor: "
+                                 "possible problem:\n%s"),
+                               qemuMessage);
+                virCopyLastError(&mon->lastError);
+                virResetLastError();
+            }
+
+            VIR_FREE(qemuMessage);
+        }
+
         if (mon->lastError.code != VIR_ERR_OK) {
             /* Already have an error, so clear any new error */
             virResetLastError();
-- 
1.8.3.2

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list




[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]