enhance processWatchdogEvent()

This patch does the following two things:
1. hold an extra reference while handling watchdog event
   If the domain is not persistent, and qemu quits unexpectedly before
   calling processWatchdogEvent(), vm will be freed and the function
   processWatchdogEvent() will be dangerous.

2. unlock qemu driver and vm before returning from processWatchdogEvent()
   When the function processWatchdogEvent() failed, we only free wdEvent,
   but forget to unlock qemu driver and vm, free dumpfile.
This commit is contained in:
Wen Congyang 2011-04-15 11:11:39 +08:00
parent 847efb32de
commit b060d2e5d4
2 changed files with 30 additions and 13 deletions

View File

@ -2442,6 +2442,9 @@ static void processWatchdogEvent(void *data, void *opaque)
struct qemuDomainWatchdogEvent *wdEvent = data;
struct qemud_driver *driver = opaque;
qemuDriverLock(driver);
virDomainObjLock(wdEvent->vm);
switch (wdEvent->action) {
case VIR_DOMAIN_WATCHDOG_ACTION_DUMP:
{
@ -2452,19 +2455,19 @@ static void processWatchdogEvent(void *data, void *opaque)
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,
@ -2481,16 +2484,23 @@ static void processWatchdogEvent(void *data, void *opaque)
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);
}

View File

@ -428,7 +428,14 @@ qemuProcessHandleWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
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();
}