[PATCH 4/6] libxl: Handle domain death events in a thread

Jim Fehlig jfehlig at suse.com
Mon Nov 29 16:38:43 UTC 2021


Similar to domain shutdown events, processing domain death events can be a
lengthy process and we don't want to block the event handler while the
operation completes. Move the death handling function to a thread.

Signed-off-by: Jim Fehlig <jfehlig at suse.com>
---
 src/libxl/libxl_domain.c | 67 ++++++++++++++++++++++++++++------------
 1 file changed, 47 insertions(+), 20 deletions(-)

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);
-- 
2.33.0





More information about the libvir-list mailing list