From 1dc6a8728bfa94666f33fda5a8db1c5f4d002afb Mon Sep 17 00:00:00 2001 From: Roman Bogorodskiy Date: Wed, 5 Aug 2026 20:28:53 +0200 Subject: [PATCH] bhyve: lock domain object while handling monitor events 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 Reviewed-by: Martin Kletzander --- src/bhyve/bhyve_monitor.c | 62 +++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/src/bhyve/bhyve_monitor.c b/src/bhyve/bhyve_monitor.c index a24696cad5..8391f10d34 100644 --- a/src/bhyve/bhyve_monitor.c +++ b/src/bhyve/bhyve_monitor.c @@ -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 * -- GitLab