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