]> xenbits.xensource.com Git - libvirt.git/commitdiff
fix a deadlock when qemu cannot start
authorWen Congyang <wency@cn.fujitsu.com>
Fri, 30 Mar 2012 06:21:49 +0000 (14:21 +0800)
committerDaniel Veillard <veillard@redhat.com>
Fri, 30 Mar 2012 06:21:49 +0000 (14:21 +0800)
When qemu cannot start, we may call qemuProcessStop() twice.
We have check whether the vm is running at the beginning of
qemuProcessStop() to avoid libvirt deadlock. We call
qemuProcessStop() with driver and vm locked. It seems that
we can avoid libvirt deadlock. But unfortunately we may
unlock driver and vm in the function qemuProcessKill() while
vm->def->id is not -1. So qemuProcessStop() will be run twice,
and monitor will be freed unexpectedly. So we should set
vm->def->id to -1 at the beginning of qemuProcessStop().

src/qemu/qemu_process.c
src/qemu/qemu_process.h

index 060e091cbde6e8b8f5f7e20f6881657291c7223d..de15c9e0ba4d54be658b359053b936c93bcdc7d4 100644 (file)
@@ -3754,9 +3754,11 @@ qemuProcessKill(struct qemud_driver *driver,
     VIR_DEBUG("vm=%s pid=%d flags=%x",
               vm->def->name, vm->pid, flags);
 
-    if (!virDomainObjIsActive(vm)) {
-        VIR_DEBUG("VM '%s' not active", vm->def->name);
-        return 0;
+    if (!(flags & VIR_QEMU_PROCESS_KILL_NOCHECK)) {
+        if (!virDomainObjIsActive(vm)) {
+            VIR_DEBUG("VM '%s' not active", vm->def->name);
+            return 0;
+        }
     }
 
     /* This loop sends SIGTERM (or SIGKILL if flags has
@@ -3860,6 +3862,13 @@ void qemuProcessStop(struct qemud_driver *driver,
         return;
     }
 
+    /*
+     * We may unlock the driver and vm in qemuProcessKill(), and another thread
+     * can lock driver and vm, and then call qemuProcessStop(). So we should
+     * set vm->def->id to -1 here to avoid qemuProcessStop() to be called twice.
+     */
+    vm->def->id = -1;
+
     if ((logfile = qemuDomainCreateLog(driver, vm, true)) < 0) {
         /* To not break the normal domain shutdown process, skip the
          * timestamp log writing if failed on opening log file. */
@@ -3922,7 +3931,8 @@ void qemuProcessStop(struct qemud_driver *driver,
     }
 
     /* shut it off for sure */
-    ignore_value(qemuProcessKill(driver, vm, VIR_QEMU_PROCESS_KILL_FORCE));
+    ignore_value(qemuProcessKill(driver, vm, VIR_QEMU_PROCESS_KILL_FORCE|
+                                             VIR_QEMU_PROCESS_KILL_NOCHECK));
 
     qemuDomainCleanupRun(driver, vm);
 
@@ -4015,7 +4025,6 @@ retry:
 
     vm->taint = 0;
     vm->pid = -1;
-    vm->def->id = -1;
     virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason);
     VIR_FREE(priv->vcpupids);
     priv->nvcpupids = 0;
index 761db6f9c69fe6a26bcad10a3e335d7827ee5fb5..5cb5ffcbe547e57577785f2a285a86c4bf84a793 100644 (file)
@@ -72,6 +72,7 @@ int qemuProcessAttach(virConnectPtr conn,
 typedef enum {
    VIR_QEMU_PROCESS_KILL_FORCE  = 1 << 0,
    VIR_QEMU_PROCESS_KILL_NOWAIT = 1 << 1,
+   VIR_QEMU_PROCESS_KILL_NOCHECK = 1 << 2, /* bypass the running vm check */
 } virQemuProcessKillMode;
 
 int qemuProcessKill(struct qemud_driver *driver,