diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index 5d0034102e..d6c5f7e5b7 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -613,12 +613,17 @@ libxlDomainShutdownThread(void *opaque) } static void -libxlDomainHandleDeath(libxlDriverPrivate *driver, virDomainObj *vm) +libxlDomainDeathThread(void *opaque) { + struct libxlEventHandlerThreadInfo *death_info = opaque; + virDomainObj *vm = death_info->vm; + libxl_event *ev = death_info->event; + libxlDriverPrivate *driver = death_info->driver; virObjectEvent *dom_event = NULL; + g_autoptr(libxlDriverConfig) cfg = libxlDriverConfigGet(driver); if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) - return; + goto cleanup; virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_DESTROYED); dom_event = virDomainEventLifecycleNewFromObj(vm, @@ -629,6 +634,11 @@ libxlDomainHandleDeath(libxlDriverPrivate *driver, virDomainObj *vm) virDomainObjListRemove(driver->domains, vm); libxlDomainObjEndJob(driver, vm); virObjectEventStateQueue(driver->domainEventState, dom_event); + + cleanup: + virDomainObjEndAPI(&vm); + libxl_event_free(cfg->ctx, ev); + VIR_FREE(death_info); } @@ -642,6 +652,9 @@ libxlDomainEventHandler(void *data, libxl_event *event) libxl_shutdown_reason xl_reason = event->u.domain_shutdown.shutdown_reason; virDomainObj *vm = NULL; g_autoptr(libxlDriverConfig) cfg = NULL; + struct libxlEventHandlerThreadInfo *thread_info = NULL; + virThread thread; + g_autofree char *thread_name = NULL; VIR_DEBUG("Received libxl event '%d' for domid '%d'", event->type, event->domid); @@ -664,31 +677,27 @@ libxlDomainEventHandler(void *data, libxl_event *event) goto cleanup; } + /* + * Start event-specific threads to handle shutdown and death. + * They are potentially lengthy operations and we don't want to be + * blocking this event handler while they are in progress. + */ if (event->type == LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN) { - struct libxlEventHandlerThreadInfo *shutdown_info = NULL; - virThread thread; - g_autofree char *name = NULL; + thread_info = g_new0(struct libxlEventHandlerThreadInfo, 1); - /* - * Start a thread to handle shutdown. We don't want to be tying up - * libxl's event machinery by doing a potentially lengthy shutdown. - */ - shutdown_info = g_new0(struct libxlEventHandlerThreadInfo, 1); - - shutdown_info->driver = driver; - shutdown_info->vm = vm; - shutdown_info->event = (libxl_event *)event; - name = g_strdup_printf("shutdown-event-%d", event->domid); + thread_info->driver = driver; + thread_info->vm = vm; + thread_info->event = (libxl_event *)event; + thread_name = g_strdup_printf("shutdown-event-%d", event->domid); /* * Cleanup will be handled by the shutdown thread. */ if (virThreadCreateFull(&thread, false, libxlDomainShutdownThread, - name, false, shutdown_info) < 0) { + thread_name, false, thread_info) < 0) { /* * Not much we can do on error here except log it. */ VIR_ERROR(_("Failed to create thread to handle domain shutdown")); - VIR_FREE(shutdown_info); goto cleanup; } /* @@ -697,15 +706,33 @@ libxlDomainEventHandler(void *data, libxl_event *event) */ return; } else if (event->type == LIBXL_EVENT_TYPE_DOMAIN_DEATH) { + thread_info = g_new0(struct libxlEventHandlerThreadInfo, 1); + + thread_info->driver = driver; + thread_info->vm = vm; + thread_info->event = (libxl_event *)event; + thread_name = g_strdup_printf("death-event-%d", event->domid); /* - * On death the domain is cleaned up from Xen's perspective. - * Cleanup on the libvirt side can be done synchronously. + * Cleanup will be handled by the death thread. */ - libxlDomainHandleDeath(driver, vm); + if (virThreadCreateFull(&thread, false, libxlDomainDeathThread, + thread_name, false, thread_info) < 0) { + /* + * Not much we can do on error here except log it. + */ + VIR_ERROR(_("Failed to create thread to handle domain death")); + goto cleanup; + } + /* + * virDomainObjEndAPI is called in the death thread, where + * libxlEventHandlerThreadInfo and libxl_event are also freed. + */ + return; } cleanup: virDomainObjEndAPI(&vm); + VIR_FREE(thread_info); cfg = libxlDriverConfigGet(driver); /* Cast away any const */ libxl_event_free(cfg->ctx, (libxl_event *)event);