mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 21:55:25 +00:00
libxl: Explicitly remove timeouts
I've noticed that libxl can invoke timeout reregister/modify hooks after returning from libxl_ctx_free. Explicitly remove the timeouts before freeing the libxl ctx to avoid executing hooks on stale objects.
This commit is contained in:
parent
889ce7460c
commit
ce33422d35
@ -79,6 +79,9 @@ struct _libxlDriverPrivate {
|
||||
char *saveDir;
|
||||
};
|
||||
|
||||
typedef struct _libxlEventHookInfo libxlEventHookInfo;
|
||||
typedef libxlEventHookInfo *libxlEventHookInfoPtr;
|
||||
|
||||
typedef struct _libxlDomainObjPrivate libxlDomainObjPrivate;
|
||||
typedef libxlDomainObjPrivate *libxlDomainObjPrivatePtr;
|
||||
struct _libxlDomainObjPrivate {
|
||||
@ -87,6 +90,9 @@ struct _libxlDomainObjPrivate {
|
||||
/* per domain libxl ctx */
|
||||
libxl_ctx *ctx;
|
||||
libxl_evgen_domain_death *deathW;
|
||||
|
||||
/* list of libxl timeout registrations */
|
||||
libxlEventHookInfoPtr timerRegistrations;
|
||||
};
|
||||
|
||||
# define LIBXL_SAVE_MAGIC "libvirt-xml\n \0 \r"
|
||||
|
@ -59,10 +59,39 @@
|
||||
/* Number of Xen scheduler parameters */
|
||||
#define XEN_SCHED_CREDIT_NPARAM 2
|
||||
|
||||
/* Append an event registration to the list of registrations */
|
||||
#define LIBXL_EV_REG_APPEND(head, add) \
|
||||
do { \
|
||||
libxlEventHookInfoPtr temp; \
|
||||
if (head) { \
|
||||
temp = head; \
|
||||
while (temp->next) \
|
||||
temp = temp->next; \
|
||||
temp->next = add; \
|
||||
} else { \
|
||||
head = add; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Remove an event registration from the list of registrations */
|
||||
#define LIBXL_EV_REG_REMOVE(head, del) \
|
||||
do { \
|
||||
libxlEventHookInfoPtr temp; \
|
||||
if (head == del) { \
|
||||
head = head->next; \
|
||||
} else { \
|
||||
temp = head; \
|
||||
while (temp->next && temp->next != del) \
|
||||
temp = temp->next; \
|
||||
if (temp->next) { \
|
||||
temp->next = del->next; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Object used to store info related to libxl event registrations */
|
||||
typedef struct _libxlEventHookInfo libxlEventHookInfo;
|
||||
typedef libxlEventHookInfo *libxlEventHookInfoPtr;
|
||||
struct _libxlEventHookInfo {
|
||||
libxlEventHookInfoPtr next;
|
||||
libxlDomainObjPrivatePtr priv;
|
||||
void *xl_priv;
|
||||
int id;
|
||||
@ -229,7 +258,12 @@ libxlTimerCallback(int timer ATTRIBUTE_UNUSED, void *timer_info)
|
||||
virObjectUnlock(p);
|
||||
libxl_osevent_occurred_timeout(p->ctx, info->xl_priv);
|
||||
virObjectLock(p);
|
||||
virEventRemoveTimeout(info->id);
|
||||
/*
|
||||
* Timeout could have been freed while the lock was dropped.
|
||||
* Only remove it from the list if it still exists.
|
||||
*/
|
||||
if (virEventRemoveTimeout(info->id) == 0)
|
||||
LIBXL_EV_REG_REMOVE(p->timerRegistrations, info);
|
||||
virObjectUnlock(p);
|
||||
}
|
||||
|
||||
@ -275,6 +309,9 @@ libxlTimeoutRegisterEventHook(void *priv,
|
||||
*/
|
||||
virObjectRef(info->priv);
|
||||
|
||||
virObjectLock(info->priv);
|
||||
LIBXL_EV_REG_APPEND(info->priv->timerRegistrations, info);
|
||||
virObjectUnlock(info->priv);
|
||||
info->xl_priv = xl_priv;
|
||||
*hndp = info;
|
||||
|
||||
@ -314,10 +351,38 @@ libxlTimeoutDeregisterEventHook(void *priv ATTRIBUTE_UNUSED,
|
||||
libxlDomainObjPrivatePtr p = info->priv;
|
||||
|
||||
virObjectLock(p);
|
||||
virEventRemoveTimeout(info->id);
|
||||
/*
|
||||
* Only remove the timeout from the list if removal from the
|
||||
* event loop is successful.
|
||||
*/
|
||||
if (virEventRemoveTimeout(info->id) == 0)
|
||||
LIBXL_EV_REG_REMOVE(p->timerRegistrations, info);
|
||||
virObjectUnlock(p);
|
||||
}
|
||||
|
||||
static void
|
||||
libxlRegisteredTimeoutsCleanup(libxlDomainObjPrivatePtr priv)
|
||||
{
|
||||
libxlEventHookInfoPtr info;
|
||||
|
||||
virObjectLock(priv);
|
||||
info = priv->timerRegistrations;
|
||||
while (info) {
|
||||
/*
|
||||
* libxl expects the event to be deregistered when calling
|
||||
* libxl_osevent_occurred_timeout, but we dont want the event info
|
||||
* destroyed. Disable the timeout and only remove it after returning
|
||||
* from libxl.
|
||||
*/
|
||||
virEventUpdateTimeout(info->id, -1);
|
||||
libxl_osevent_occurred_timeout(priv->ctx, info->xl_priv);
|
||||
virEventRemoveTimeout(info->id);
|
||||
info = info->next;
|
||||
}
|
||||
priv->timerRegistrations = NULL;
|
||||
virObjectUnlock(priv);
|
||||
}
|
||||
|
||||
static const libxl_osevent_hooks libxl_event_callbacks = {
|
||||
.fd_register = libxlFDRegisterEventHook,
|
||||
.fd_modify = libxlFDModifyEventHook,
|
||||
@ -571,6 +636,8 @@ libxlVmCleanup(libxlDriverPrivatePtr driver,
|
||||
vm->def->id = -1;
|
||||
vm->newDef = NULL;
|
||||
}
|
||||
|
||||
libxlRegisteredTimeoutsCleanup(priv);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user