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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list