[PATCH 5/5] KVM test: Verify qemu process before throwing monitor exceptions

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

 



When qemu suffers a segmentation fault, monitor code might still
want to issue commands to a VM, masking the segmentation fault.

So, pass the vm object to the monitor code, and before throwing
monitor exceptions, verify the state of the qemu process (whether
it crashed or not), and throw the QemuSegFaultError if the process
crashed:

22:08:44 DEBUG| QemuSegFaultError: Qemu crashed: /bin/sh: line 1:  6847
Aborted                 (core dumped)

This will make analyzing such failures much easier.

Signed-off-by: Lucas Meneghel Rodrigues <lmr@xxxxxxxxxx>
---
 client/virt/kvm_monitor.py |   24 ++++++++++++++++++++++--
 client/virt/kvm_vm.py      |   10 ++++++----
 2 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/client/virt/kvm_monitor.py b/client/virt/kvm_monitor.py
index efd6aa3..049c28f 100644
--- a/client/virt/kvm_monitor.py
+++ b/client/virt/kvm_monitor.py
@@ -77,6 +77,7 @@ class Monitor:
         try:
             self._socket.connect(filename)
         except socket.error:
+            self.vm.verify_userspace_crash()
             raise MonitorConnectError("Could not connect to monitor socket")
 
 
@@ -124,6 +125,7 @@ class Monitor:
         try:
             return bool(select.select([self._socket], [], [], timeout)[0])
         except socket.error, e:
+            self.vm.verify_userspace_crash()
             raise MonitorSocketError("Verifying data on monitor socket", e)
 
 
@@ -133,6 +135,7 @@ class Monitor:
             try:
                 data = self._socket.recv(1024)
             except socket.error, e:
+                self.vm.verify_userspace_crash()
                 raise MonitorSocketError("Could not receive data from monitor",
                                          e)
             if not data:
@@ -157,7 +160,7 @@ class HumanMonitor(Monitor):
     Wraps "human monitor" commands.
     """
 
-    def __init__(self, name, filename, suppress_exceptions=False):
+    def __init__(self, name, filename, vm, suppress_exceptions=False):
         """
         Connect to the monitor socket and find the (qemu) prompt.
 
@@ -174,10 +177,12 @@ class HumanMonitor(Monitor):
             Monitor.__init__(self, name, filename)
 
             self.protocol = "human"
+            self.vm = vm
 
             # Find the initial (qemu) prompt
             s, o = self._read_up_to_qemu_prompt(20)
             if not s:
+                self.vm.verify_userspace_crash()
                 raise MonitorProtocolError("Could not find (qemu) prompt "
                                            "after connecting to monitor. "
                                            "Output so far: %r" % o)
@@ -190,6 +195,7 @@ class HumanMonitor(Monitor):
             if suppress_exceptions:
                 logging.warn(e)
             else:
+                self.vm.verify_userspace_crash()
                 raise
 
 
@@ -220,6 +226,7 @@ class HumanMonitor(Monitor):
         @raise MonitorSocketError: Raised if a socket error occurs
         """
         if not self._acquire_lock(20):
+            self.vm.verify_userspace_crash()
             raise MonitorLockError("Could not acquire exclusive lock to send "
                                    "monitor command '%s'" % cmd)
 
@@ -227,6 +234,7 @@ class HumanMonitor(Monitor):
             try:
                 self._socket.sendall(cmd + "\n")
             except socket.error, e:
+                self.vm.verify_userspace_crash()
                 raise MonitorSocketError("Could not send monitor command %r" %
                                          cmd, e)
 
@@ -253,6 +261,7 @@ class HumanMonitor(Monitor):
             logging.debug("(monitor %s) Sending command '%s'",
                           self.name, command)
         if not self._acquire_lock(20):
+            self.vm.verify_userspace_crash()
             raise MonitorLockError("Could not acquire exclusive lock to send "
                                    "monitor command '%s'" % command)
 
@@ -283,6 +292,7 @@ class HumanMonitor(Monitor):
             else:
                 msg = ("Could not find (qemu) prompt after command '%s'. "
                        "Output so far: %r" % (command, o))
+                self.vm.verify_userspace_crash()
                 raise MonitorProtocolError(msg)
 
         finally:
@@ -464,7 +474,7 @@ class QMPMonitor(Monitor):
     Wraps QMP monitor commands.
     """
 
-    def __init__(self, name, filename, suppress_exceptions=False):
+    def __init__(self, name, filename, vm, suppress_exceptions=False):
         """
         Connect to the monitor socket, read the greeting message and issue the
         qmp_capabilities command.  Also make sure the json module is available.
@@ -486,6 +496,7 @@ class QMPMonitor(Monitor):
             self.protocol = "qmp"
             self._greeting = None
             self._events = []
+            self.vm = vm
 
             # Make sure json is available
             try:
@@ -505,6 +516,7 @@ class QMPMonitor(Monitor):
                     break
                 time.sleep(0.1)
             else:
+                self.vm.verify_userspace_crash()
                 raise MonitorProtocolError("No QMP greeting message received")
 
             # Issue qmp_capabilities
@@ -515,6 +527,7 @@ class QMPMonitor(Monitor):
             if suppress_exceptions:
                 logging.warn(e)
             else:
+                self.vm.verify_userspace_crash()
                 raise
 
 
@@ -578,6 +591,7 @@ class QMPMonitor(Monitor):
         try:
             self._socket.sendall(data)
         except socket.error, e:
+            self.vm.verify_userspace_crash()
             raise MonitorSocketError("Could not send data: %r" % data, e)
 
 
@@ -623,6 +637,7 @@ class QMPMonitor(Monitor):
             logging.debug("(monitor %s) Sending command '%s'",
                           self.name, cmd)
         if not self._acquire_lock(20):
+            self.vm.verify_userspace_crash()
             raise MonitorLockError("Could not acquire exclusive lock to send "
                                    "QMP command '%s'" % cmd)
 
@@ -635,6 +650,7 @@ class QMPMonitor(Monitor):
             # Read response
             r = self._get_response(id, timeout)
             if r is None:
+                self.vm.verify_userspace_crash()
                 raise MonitorProtocolError("Received no response to QMP "
                                            "command '%s', or received a "
                                            "response with an incorrect id"
@@ -648,6 +664,7 @@ class QMPMonitor(Monitor):
                         logging.debug("(monitor %s)    %s", self.name, l)
                 return r["return"]
             if "error" in r:
+                self.vm.verify_userspace_crash()
                 raise QMPCmdError(cmd, args, r["error"])
 
         finally:
@@ -668,6 +685,7 @@ class QMPMonitor(Monitor):
         @raise MonitorProtocolError: Raised if no response is received
         """
         if not self._acquire_lock(20):
+            self.vm.verify_userspace_crash()
             raise MonitorLockError("Could not acquire exclusive lock to send "
                                    "data: %r" % data)
 
@@ -676,6 +694,7 @@ class QMPMonitor(Monitor):
             self._send(data)
             r = self._get_response(None, timeout)
             if r is None:
+                self.vm.verify_userspace_crash()
                 raise MonitorProtocolError("Received no response to data: %r" %
                                            data)
             return r
@@ -778,6 +797,7 @@ class QMPMonitor(Monitor):
         @raise MonitorLockError: Raised if the lock cannot be acquired
         """
         if not self._acquire_lock(20):
+            self.vm.verify_userspace_crash()
             raise MonitorLockError("Could not acquire exclusive lock to clear "
                                    "QMP event list")
         self._events = []
diff --git a/client/virt/kvm_vm.py b/client/virt/kvm_vm.py
index 372cfbc..0f62170 100644
--- a/client/virt/kvm_vm.py
+++ b/client/virt/kvm_vm.py
@@ -834,13 +834,15 @@ class VM(virt_vm.BaseVM):
                         if monitor_params.get("monitor_type") == "qmp":
                             # Add a QMP monitor
                             monitor = kvm_monitor.QMPMonitor(
-                                monitor_name,
-                                self.get_monitor_filename(monitor_name))
+                                name=monitor_name,
+                                filename=self.get_monitor_filename(monitor_name),
+                                vm=self)
                         else:
                             # Add a "human" monitor
                             monitor = kvm_monitor.HumanMonitor(
-                                monitor_name,
-                                self.get_monitor_filename(monitor_name))
+                                name=monitor_name,
+                                filename=self.get_monitor_filename(monitor_name),
+                                vm=self)
                         monitor.verify_responsive()
                         break
                     except kvm_monitor.MonitorError, e:
-- 
1.7.7

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux