Exit the monitor right after we've done with it to get
the virDomainObjPtr lock back, otherwise we might be accessing
vm->def while it's being cleaned up by qemuProcessStop.
If the domain crashed while we were in the monitor, exit
early instead of changing vm->def which is now the persistent
definition.
---
src/qemu/qemu_driver.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 07b061e..20b54cc 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4443,7 +4443,7 @@ static int qemuDomainHotplugVcpus(virQEMUDriverPtr driver,
if (rc == 0)
goto unsupported;
if (rc < 0)
- goto cleanup;
+ goto exit_monitor;
vcpus++;
}
@@ -4454,7 +4454,7 @@ static int qemuDomainHotplugVcpus(virQEMUDriverPtr driver,
if (rc == 0)
goto unsupported;
if (rc < 0)
- goto cleanup;
+ goto exit_monitor;
vcpus--;
}
@@ -4471,6 +4471,10 @@ static int qemuDomainHotplugVcpus(virQEMUDriverPtr driver,
* fatal */
if ((ncpupids = qemuMonitorGetCPUInfo(priv->mon, &cpupids)) <= 0) {
virResetLastError();
+ goto exit_monitor;
+ }
+ if (qemuDomainObjExitMonitorAlive(driver, vm) < 0) {
+ ret = -1;
goto cleanup;
}
@@ -4591,10 +4595,10 @@ static int qemuDomainHotplugVcpus(virQEMUDriverPtr driver,
cpupids = NULL;
cleanup:
- qemuDomainObjExitMonitor(driver, vm);
- vm->def->vcpus = vcpus;
VIR_FREE(cpupids);
VIR_FREE(mem_mask);
+ if (virDomainObjIsActive(vm))
+ vm->def->vcpus = vcpus;
virDomainAuditVcpu(vm, oldvcpus, nvcpus, "update", rc == 1);
if (cgroup_vcpu)
virCgroupFree(&cgroup_vcpu);
@@ -4603,6 +4607,8 @@ static int qemuDomainHotplugVcpus(virQEMUDriverPtr driver,
unsupported:
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("cannot change vcpu count of this domain"));
+ exit_monitor:
+ qemuDomainObjExitMonitor(driver, vm);
goto cleanup;
}
--
2.0.4