[libvirt] [PATCH] Allow destroying QEMU VM even if a job is active

Daniel P. Berrange berrange at redhat.com
Fri May 6 11:57:00 UTC 2011


Introduce a virProcessKill function that can be safely called
even when the job mutex is held. This allows virDomainDestroy
to kill any VM even if it is asleep in a monitor job. The PID
will die and the thread asleep on the monitor will then wake
up releasing the job mutex.

* src/qemu/qemu_driver.c: Kill process before using qemuProcessStop
  to ensure job is released
* src/qemu/qemu_process.c: Add virProcessKill for killing off
  QEMU processes
---
 src/qemu/qemu_driver.c  |    7 +++++++
 src/qemu/qemu_process.c |   39 +++++++++++++++++++++++++++++++--------
 src/qemu/qemu_process.h |    2 ++
 3 files changed, 40 insertions(+), 8 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index b3f9e00..6d6fb51 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -1482,6 +1482,13 @@ static int qemudDomainDestroy(virDomainPtr dom) {
         goto cleanup;
     }
 
+    /* Although qemuProcessStop does this already, there may
+     * be an outstanding job active. We want to make sure we
+     * can kill the process even if a job is active. Killing
+     * it now, means the job will be released
+     */
+    qemuProcessKill(vm);
+
     if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
         goto cleanup;
 
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index a6c0dc8..c60c51f 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -2369,6 +2369,36 @@ cleanup:
 }
 
 
+void qemuProcessKill(virDomainObjPtr vm)
+{
+    int i;
+    int rc;
+    VIR_DEBUG("vm=%s pid=%d", vm->def->name, vm->pid);
+
+    if (!virDomainObjIsActive(vm)) {
+        VIR_DEBUG("VM '%s' not active", vm->def->name);
+        return;
+    }
+
+    for (i = 0 ; i < 15 ; i++) {
+        int signum;
+        if (i == 0)
+            signum = SIGTERM;
+        else if (i == 8)
+            signum = SIGKILL;
+        else
+            signum = 0; /* Just check for existance */
+
+        rc = virKillProcess(vm->pid, signum);
+        VIR_DEBUG("Iteration %d rc=%d", i, rc);
+        if (rc < 0)
+            break;
+
+        usleep(200 * 1000);
+    }
+}
+
+
 void qemuProcessStop(struct qemud_driver *driver,
                      virDomainObjPtr vm,
                      int migrated)
@@ -2436,13 +2466,6 @@ void qemuProcessStop(struct qemud_driver *driver,
         }
     }
 
-    /* This will safely handle a non-running guest with pid=0 or pid=-1*/
-    if (virKillProcess(vm->pid, 0) == 0 &&
-        virKillProcess(vm->pid, SIGTERM) < 0)
-        virReportSystemError(errno,
-                             _("Failed to send SIGTERM to %s (%d)"),
-                             vm->def->name, vm->pid);
-
     if (priv->mon)
         qemuMonitorClose(priv->mon);
 
@@ -2454,7 +2477,7 @@ void qemuProcessStop(struct qemud_driver *driver,
     }
 
     /* shut it off for sure */
-    virKillProcess(vm->pid, SIGKILL);
+    qemuProcessKill(vm);
 
     /* now that we know it's stopped call the hook if present */
     if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h
index f1ab599..d8afab0 100644
--- a/src/qemu/qemu_process.h
+++ b/src/qemu/qemu_process.h
@@ -49,4 +49,6 @@ void qemuProcessStop(struct qemud_driver *driver,
                      virDomainObjPtr vm,
                      int migrated);
 
+void qemuProcessKill(virDomainObjPtr vm);
+
 #endif /* __QEMU_PROCESS_H__ */
-- 
1.7.4.4




More information about the libvir-list mailing list