* can kill the process even if a job is active. Killing
* it now means the job will be released
*/
- qemuProcessKill(vm);
+ qemuProcessKill(vm, false);
if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_DESTROY) < 0)
goto cleanup;
cleanup:
if (vm) {
if (ret == -1)
- qemuProcessKill(vm);
+ qemuProcessKill(vm, false);
if (virDomainObjUnref(vm) > 0)
virDomainObjUnlock(vm);
}
VIR_DEBUG("vm=%p", vm);
virDomainObjLock(vm);
+ if (priv->gotShutdown) {
+ VIR_DEBUG("Ignoring repeated SHUTDOWN event from domain %s",
+ vm->def->name);
+ goto cleanup;
+ }
+
priv->gotShutdown = true;
if (priv->fakeReboot) {
virDomainObjRef(vm);
qemuProcessFakeReboot,
vm) < 0) {
VIR_ERROR(_("Failed to create reboot thread, killing domain"));
- qemuProcessKill(vm);
+ qemuProcessKill(vm, true);
if (virDomainObjUnref(vm) == 0)
vm = NULL;
}
} else {
- qemuProcessKill(vm);
+ qemuProcessKill(vm, true);
}
+
+cleanup:
if (vm)
virDomainObjUnlock(vm);
-
return 0;
}
}
-void qemuProcessKill(virDomainObjPtr vm)
+void qemuProcessKill(virDomainObjPtr vm, bool gracefully)
{
int i;
- VIR_DEBUG("vm=%s pid=%d", vm->def->name, vm->pid);
+ VIR_DEBUG("vm=%s pid=%d gracefully=%d",
+ vm->def->name, vm->pid, gracefully);
if (!virDomainObjIsActive(vm)) {
VIR_DEBUG("VM '%s' not active", vm->def->name);
break;
}
+ if (i == 0 && gracefully)
+ break;
+
usleep(200 * 1000);
}
}
}
/* shut it off for sure */
- qemuProcessKill(vm);
+ qemuProcessKill(vm, false);
/* Stop autodestroy in case guest is restarted */
qemuProcessAutoDestroyRemove(driver, vm);
virDomainChrSourceDefPtr monConfig,
bool monJSON);
-void qemuProcessKill(virDomainObjPtr vm);
+void qemuProcessKill(virDomainObjPtr vm, bool gracefully);
int qemuProcessAutoDestroyInit(struct qemud_driver *driver);
void qemuProcessAutoDestroyRun(struct qemud_driver *driver,