On Mon, Jan 21, 2013 at 12:22:22PM -0700, Jim Fehlig wrote:
> 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.
> ---
> src/libxl/libxl_conf.h | 6 ++++
> src/libxl/libxl_driver.c | 71
> +++++++++++++++++++++++++++++++++++++++++++++---
> 2 files changed, 73 insertions(+), 4 deletions(-)
>
> diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h
> index 3d5a461..f6167e6 100644
> --- a/src/libxl/libxl_conf.h
> +++ b/src/libxl/libxl_conf.h
> @@ -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"
> diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
> index 530a17f..08dffd6 100644
> --- a/src/libxl/libxl_driver.c
> +++ b/src/libxl/libxl_driver.c
> @@ -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;
> @@ -225,7 +254,11 @@ 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);
> }
>
> @@ -269,6 +302,9 @@ libxlTimeoutRegisterEventHook(void *priv,
> event objects. */
> virObjectRef(info->priv);
>
> + virObjectLock(info->priv);
> + LIBXL_EV_REG_APPEND(info->priv->timerRegistrations, info);
> + virObjectUnlock(info->priv);
> info->xl_priv = xl_priv;
> *hndp = info;
>
> @@ -308,10 +344,35 @@ 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,
> @@ -565,6 +626,8 @@ libxlVmCleanup(libxlDriverPrivatePtr driver,
> vm->def->id = -1;
> vm->newDef = NULL;
> }
> +
> + libxlRegisteredTimeoutsCleanup(priv);
> }
>
> /*
ACK, just one small nit, usually we format multi-line comments as
/*
* bla
* bla
*/
could you update your patches accordingly :-) ?
thanks !
Daniel
--
Daniel Veillard | Open Source and Standards, Red Hat
[email protected] | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
http://veillard.com/ | virtualization library http://libvirt.org/
--
libvir-list mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/libvir-list