]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
bhyve: lock domain object while handling monitor events
authorRoman Bogorodskiy <bogorodskiy@gmail.com>
Wed, 5 Aug 2026 18:28:53 +0000 (20:28 +0200)
committerRoman Bogorodskiy <bogorodskiy@gmail.com>
Thu, 6 Aug 2026 16:18:37 +0000 (18:18 +0200)
virBhyveProcessStop() calls virBhyveDomainObjStopWorker(), which expects
the domain object to be locked. It temporarily releases the lock while
stopping the event thread and acquires it again before returning.

bhyveMonitorIO() called the process stop and restart paths without
holding the domain lock. As a result, the lock acquired by
virBhyveDomainObjStopWorker() was never released, causing subsequent
domain API calls to hang after the guest exited.

Lock the domain object while processing the bhyve process exit event and
release it after the stop or restart operation completes.

Fixes: 0041788857dafa46e047c09c90039209a642cb85 ("bhyve: clean up event thread")
Signed-off-by: Roman Bogorodskiy <bogorodskiy@gmail.com>
Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
src/bhyve/bhyve_monitor.c

index a24696cad5bdc0fb533134143f814eaaf6612715..8391f10d347a5b0743402d205a43786efa32b732 100644 (file)
@@ -139,37 +139,43 @@ bhyveMonitorIO(int watch, int kq, int events G_GNUC_UNUSED, void *opaque)
         return;
     }
 
-    if (kev.filter == EVFILT_PROC && (kev.fflags & NOTE_EXIT) != 0) {
-        if ((pid_t)kev.ident != vm->pid) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("event from unexpected proc %1$ju!=%2$ju"),
-                           (uintmax_t)vm->pid, (uintmax_t)kev.ident);
-            return;
-        }
+    if (kev.filter != EVFILT_PROC || (kev.fflags & NOTE_EXIT) == 0)
+        return;
+
+    virObjectLock(vm);
+
+    if ((pid_t)kev.ident != vm->pid) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("event from unexpected proc %1$ju!=%2$ju"),
+                       (uintmax_t)vm->pid, (uintmax_t)kev.ident);
+        goto cleanup;
+    }
 
-        name = vm->def->name;
-        status = kev.data;
-        if (WIFSIGNALED(status) && WCOREDUMP(status)) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("Guest %1$s got signal %2$d and crashed"),
-                           name, WTERMSIG(status));
-            virBhyveProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_CRASHED, false);
-        } else if (WIFEXITED(status)) {
-            if (WEXITSTATUS(status) == 0 || mon->reboot) {
-                /* 0 - reboot */
-                VIR_INFO("Guest %s rebooted; restarting domain.", name);
-                virBhyveProcessRestart(driver, vm);
-            } else if (WEXITSTATUS(status) < 3) {
-                /* 1 - shutdown, 2 - halt, 3 - triple fault. others - error */
-                VIR_INFO("Guest %s shut itself down; destroying domain.", name);
-                virBhyveProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN, false);
-            } else {
-                VIR_INFO("Guest %s had an error and exited with status %d; destroying domain.",
-                         name, WEXITSTATUS(status));
-                virBhyveProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_UNKNOWN, false);
-            }
+    name = vm->def->name;
+    status = kev.data;
+    if (WIFSIGNALED(status) && WCOREDUMP(status)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Guest %1$s got signal %2$d and crashed"),
+                       name, WTERMSIG(status));
+        virBhyveProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_CRASHED, false);
+    } else if (WIFEXITED(status)) {
+        if (WEXITSTATUS(status) == 0 || mon->reboot) {
+            /* 0 - reboot */
+            VIR_INFO("Guest %s rebooted; restarting domain.", name);
+            virBhyveProcessRestart(driver, vm);
+        } else if (WEXITSTATUS(status) < 3) {
+            /* 1 - shutdown, 2 - halt, 3 - triple fault. others - error */
+            VIR_INFO("Guest %s shut itself down; destroying domain.", name);
+            virBhyveProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN, false);
+        } else {
+            VIR_INFO("Guest %s had an error and exited with status %d; destroying domain.",
+                     name, WEXITSTATUS(status));
+            virBhyveProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_UNKNOWN, false);
         }
     }
+
+ cleanup:
+    virObjectUnlock(vm);
 }
 
 static bhyveMonitor *