struct qemuDomainWatchdogEvent *wdEvent = data;
struct qemud_driver *driver = opaque;
+ qemuDriverLock(driver);
+ virDomainObjLock(wdEvent->vm);
+
switch (wdEvent->action) {
case VIR_DOMAIN_WATCHDOG_ACTION_DUMP:
{
wdEvent->vm->def->name,
(unsigned int)time(NULL)) < 0) {
virReportOOMError();
- break;
+ goto unlock;
}
- qemuDriverLock(driver);
- virDomainObjLock(wdEvent->vm);
-
- if (qemuDomainObjBeginJobWithDriver(driver, wdEvent->vm) < 0)
- break;
+ if (qemuDomainObjBeginJobWithDriver(driver, wdEvent->vm) < 0) {
+ VIR_FREE(dumpfile);
+ goto unlock;
+ }
if (!virDomainObjIsActive(wdEvent->vm)) {
qemuReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("domain is not running"));
- break;
+ VIR_FREE(dumpfile);
+ goto endjob;
}
ret = doCoreDump(driver,
qemuReportError(VIR_ERR_OPERATION_FAILED,
"%s", _("Resuming after dump failed"));
- if (qemuDomainObjEndJob(wdEvent->vm) > 0)
- virDomainObjUnlock(wdEvent->vm);
-
- qemuDriverUnlock(driver);
-
VIR_FREE(dumpfile);
}
break;
+ default:
+ goto unlock;
}
+endjob:
+ /* Safe to ignore value since ref count was incremented in
+ * qemuProcessHandleWatchdog().
+ */
+ ignore_value(qemuDomainObjEndJob(wdEvent->vm));
+
+unlock:
+ if (virDomainObjUnref(wdEvent->vm) > 0)
+ virDomainObjUnlock(wdEvent->vm);
+ qemuDriverUnlock(driver);
VIR_FREE(wdEvent);
}
if (VIR_ALLOC(wdEvent) == 0) {
wdEvent->action = VIR_DOMAIN_WATCHDOG_ACTION_DUMP;
wdEvent->vm = vm;
- ignore_value(virThreadPoolSendJob(driver->workerPool, wdEvent));
+ /* Hold an extra reference because we can't allow 'vm' to be
+ * deleted before handling watchdog event is finished.
+ */
+ virDomainObjRef(vm);
+ if (virThreadPoolSendJob(driver->workerPool, wdEvent) < 0) {
+ virDomainObjUnref(vm);
+ VIR_FREE(wdEvent);
+ }
} else
virReportOOMError();
}