Martin Kletzander wrote:
> On Thu, Aug 06, 2026 at 10:03:33AM +0200, Roman Bogorodskiy wrote:
> > 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 <[email protected]>
> > ---
> > src/bhyve/bhyve_monitor.c | 7 ++++++-
> > 1 file changed, 6 insertions(+), 1 deletion(-)
> >
> > diff --git a/src/bhyve/bhyve_monitor.c b/src/bhyve/bhyve_monitor.c
> > index a24696cad5..a7d7588ee5 100644
> > --- a/src/bhyve/bhyve_monitor.c
> > +++ b/src/bhyve/bhyve_monitor.c
> > @@ -140,11 +140,13 @@ bhyveMonitorIO(int watch, int kq, int events
> > G_GNUC_UNUSED, void *opaque)
> > }
> >
> > if (kev.filter == EVFILT_PROC && (kev.fflags & NOTE_EXIT) != 0) {
>
> If this condition is false you do not lock the vm, but ...
>
> > + 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);
> > - return;
> > + goto cleanup;
> > }
> >
> > name = vm->def->name;
> > @@ -169,6 +171,9 @@ bhyveMonitorIO(int watch, int kq, int events
> > G_GNUC_UNUSED, void *opaque)
> > virBhyveProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_UNKNOWN,
> > false);
> > }
> > }
> > +
> > + cleanup:
> > + virObjectUnlock(vm);
>
> ... you try to unlock it anyway. The commit message sounds like it
> might even be wanted, which I doubt. But even if it was, such functions
> are source of a lot of problems.
Hm, it might look like that in a diff, but both virObjectLock() and
virObjectUnlock() are called in body of
"if (kev.filter == EVFILT_PROC && (kev.fflags & NOTE_EXIT) != 0) {".
So I believe there should be no unmatched lock/unlock calls, if I'm not
missing something.