1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2025-01-27 18:03:50 +03:00

qemu: Avoid deadlock in autodestroy

Since closeCallbacks were turned into virObjectLockable, we can no
longer call virQEMUCloseCallbacks APIs from within a registered close
callback.
This commit is contained in:
Jiri Denemark 2013-02-15 15:11:47 +01:00
parent 3898ba7f2c
commit 568a6cda27
4 changed files with 19 additions and 17 deletions

View File

@ -810,33 +810,22 @@ struct virQEMUCloseCallbacksData {
static void
virQEMUCloseCallbacksRunOne(void *payload,
const void *name,
const void *uuid,
void *opaque)
{
struct virQEMUCloseCallbacksData *data = opaque;
qemuDriverCloseDefPtr closeDef = payload;
unsigned char uuid[VIR_UUID_BUFLEN];
char uuidstr[VIR_UUID_STRING_BUFLEN];
virDomainObjPtr dom;
VIR_DEBUG("conn=%p, thisconn=%p, uuid=%s, cb=%p",
closeDef->conn, data->conn, (const char *)name, closeDef->cb);
closeDef->conn, data->conn, (const char *) uuid, closeDef->cb);
if (data->conn != closeDef->conn || !closeDef->cb)
return;
if (virUUIDParse(name, uuid) < 0) {
VIR_WARN("Failed to parse %s", (const char *)name);
return;
}
/* We need to reformat uuidstr, because closeDef->cb
* might cause the current hash entry to be removed,
* which means 'name' will have been free()d
*/
virUUIDFormat(uuid, uuidstr);
if (!(dom = virDomainObjListFindByUUID(data->driver->domains, uuid))) {
VIR_DEBUG("No domain object with UUID %s", uuidstr);
VIR_DEBUG("No domain object with UUID %s",
(const char *) uuid);
return;
}
@ -844,7 +833,7 @@ virQEMUCloseCallbacksRunOne(void *payload,
if (dom)
virObjectUnlock(dom);
virHashRemoveEntry(data->list, uuidstr);
virHashRemoveEntry(data->list, uuid);
}
void

View File

@ -254,6 +254,10 @@ struct qemuDomainDiskInfo {
int io_status;
};
/*
* To avoid a certain deadlock this callback must never call any
* virQEMUCloseCallbacks* API.
*/
typedef virDomainObjPtr (*virQEMUCloseCallback)(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virConnectPtr conn);

View File

@ -137,6 +137,7 @@ struct _qemuDomainObjPrivate {
bool gotShutdown;
bool beingDestroyed;
bool autoDestroyed;
char *pidfile;
int nvcpupids;

View File

@ -4223,7 +4223,8 @@ void qemuProcessStop(virQEMUDriverPtr driver,
qemuDomainCleanupRun(driver, vm);
/* Stop autodestroy in case guest is restarted */
qemuProcessAutoDestroyRemove(driver, vm);
if (!priv->autoDestroyed)
qemuProcessAutoDestroyRemove(driver, vm);
/* now that we know it's stopped call the hook if present */
if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
@ -4603,8 +4604,15 @@ qemuProcessAutoDestroy(virQEMUDriverPtr driver,
goto cleanup;
VIR_DEBUG("Killing domain");
/* We need to prevent qemuProcessStop from removing this function from
* closeCallbacks since that would cause a deadlock.
*/
priv->autoDestroyed = true;
qemuProcessStop(driver, dom, VIR_DOMAIN_SHUTOFF_DESTROYED,
VIR_QEMU_PROCESS_STOP_MIGRATED);
priv->autoDestroyed = false;
virDomainAuditStop(dom, "destroyed");
event = virDomainEventNewFromObj(dom,
VIR_DOMAIN_EVENT_STOPPED,