From ff68d6eeb5bca38050f4fc53108237b738b906fa Mon Sep 17 00:00:00 2001 From: Wen Congyang Date: Fri, 30 Mar 2012 14:21:49 +0800 Subject: [PATCH] fix a deadlock when qemu cannot start 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 | 19 ++++++++++++++----- src/qemu/qemu_process.h | 1 + 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 060e091cbd..de15c9e0ba 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -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; diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h index 761db6f9c6..5cb5ffcbe5 100644 --- a/src/qemu/qemu_process.h +++ b/src/qemu/qemu_process.h @@ -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, -- GitLab