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:
parent
3898ba7f2c
commit
568a6cda27
@ -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
|
||||
|
@ -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);
|
||||
|
@ -137,6 +137,7 @@ struct _qemuDomainObjPrivate {
|
||||
|
||||
bool gotShutdown;
|
||||
bool beingDestroyed;
|
||||
bool autoDestroyed;
|
||||
char *pidfile;
|
||||
|
||||
int nvcpupids;
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user