char *saveDir;
};
+typedef struct _libxlEventHookInfo libxlEventHookInfo;
+typedef libxlEventHookInfo *libxlEventHookInfoPtr;
+
typedef struct _libxlDomainObjPrivate libxlDomainObjPrivate;
typedef libxlDomainObjPrivate *libxlDomainObjPrivatePtr;
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"
/* 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;
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);
}
*/
virObjectRef(info->priv);
+ virObjectLock(info->priv);
+ LIBXL_EV_REG_APPEND(info->priv->timerRegistrations, info);
+ virObjectUnlock(info->priv);
info->xl_priv = xl_priv;
*hndp = info;
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,
vm->def->id = -1;
vm->newDef = NULL;
}
+
+ libxlRegisteredTimeoutsCleanup(priv);
}
/*