Signed-off-by: Ryan Moeller <ryan@xxxxxxxxxxxxx> --- src/bhyve/bhyve_monitor.c | 144 ++++++++++++++++++++++++++------------ 1 file changed, 98 insertions(+), 46 deletions(-) diff --git a/src/bhyve/bhyve_monitor.c b/src/bhyve/bhyve_monitor.c index 0e55e19772..566c672ba0 100644 --- a/src/bhyve/bhyve_monitor.c +++ b/src/bhyve/bhyve_monitor.c @@ -32,24 +32,82 @@ #include "virerror.h" #include "virfile.h" #include "virlog.h" +#include "virobject.h" #define VIR_FROM_THIS VIR_FROM_BHYVE VIR_LOG_INIT("bhyve.bhyve_monitor"); struct _bhyveMonitor { + virObject parent; + int kq; int watch; bhyveConnPtr driver; + virDomainObjPtr vm; }; +static virClassPtr bhyveMonitorClass; + +static void +bhyveMonitorDispose(void *obj) +{ + bhyveMonitorPtr mon = obj; + + VIR_FORCE_CLOSE(mon->kq); + virObjectUnref(mon->vm); +} + +static int +bhyveMonitorOnceInit(void) +{ + if (!VIR_CLASS_NEW(bhyveMonitor, virClassForObject())) + return -1; + + return 0; +} + +VIR_ONCE_GLOBAL_INIT(bhyveMonitor); + +static void bhyveMonitorIO(int, int, int, void *); + +static bool +bhyveMonitorRegister(bhyveMonitorPtr mon) +{ + virObjectRef(mon); + mon->watch = virEventAddHandle(mon->kq, + VIR_EVENT_HANDLE_READABLE | + VIR_EVENT_HANDLE_ERROR | + VIR_EVENT_HANDLE_HANGUP, + bhyveMonitorIO, + mon, + virObjectFreeCallback); + if (mon->watch < 0) { + VIR_DEBUG("failed to add event handle for mon %p", mon); + virObjectUnref(mon); + return false; + } + return true; +} + +static void +bhyveMonitorUnregister(bhyveMonitorPtr mon) +{ + if (mon->watch < 0) + return; + + virEventRemoveHandle(mon->watch); + mon->watch = -1; +} + static void bhyveMonitorIO(int watch, int kq, int events G_GNUC_UNUSED, void *opaque) { const struct timespec zerowait = { 0, 0 }; - virDomainObjPtr vm = opaque; - bhyveDomainObjPrivatePtr priv = vm->privateData; - bhyveMonitorPtr mon = priv->mon; + bhyveMonitorPtr mon = opaque; + virDomainObjPtr vm = mon->vm; + bhyveConnPtr driver = mon->driver; + const char *name; struct kevent kev; int rc, status; @@ -82,60 +140,49 @@ bhyveMonitorIO(int watch, int kq, int events G_GNUC_UNUSED, void *opaque) return; } + name = vm->def->name; status = kev.data; if (WIFSIGNALED(status) && WCOREDUMP(status)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Guest %s got signal %d and crashed"), - vm->def->name, - WTERMSIG(status)); - virBhyveProcessStop(mon->driver, vm, - VIR_DOMAIN_SHUTOFF_CRASHED); + name, WTERMSIG(status)); + virBhyveProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_CRASHED); } else if (WIFEXITED(status)) { if (WEXITSTATUS(status) == 0) { /* 0 - reboot */ /* TODO: Implementing reboot is a little more complicated. */ - VIR_INFO("Guest %s rebooted; destroying domain.", - vm->def->name); - virBhyveProcessStop(mon->driver, vm, - VIR_DOMAIN_SHUTOFF_SHUTDOWN); + VIR_INFO("Guest %s rebooted; restarting domain.", name); + virBhyveProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN); } else if (WEXITSTATUS(status) < 3) { /* 1 - shutdown, 2 - halt, 3 - triple fault. others - error */ - VIR_INFO("Guest %s shut itself down; destroying domain.", - vm->def->name); - virBhyveProcessStop(mon->driver, vm, - VIR_DOMAIN_SHUTOFF_SHUTDOWN); + VIR_INFO("Guest %s shut itself down; destroying domain.", name); + virBhyveProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN); } else { VIR_INFO("Guest %s had an error and exited with status %d; destroying domain.", - vm->def->name, WEXITSTATUS(status)); - virBhyveProcessStop(mon->driver, vm, - VIR_DOMAIN_SHUTOFF_UNKNOWN); + name, WEXITSTATUS(status)); + virBhyveProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_UNKNOWN); } } } } -static void -bhyveMonitorRelease(void *opaque) -{ - virDomainObjPtr vm = opaque; - bhyveDomainObjPrivatePtr priv = vm->privateData; - bhyveMonitorPtr mon = priv->mon; - - VIR_FORCE_CLOSE(mon->kq); - VIR_FREE(mon); -} - -bhyveMonitorPtr -bhyveMonitorOpen(virDomainObjPtr vm, bhyveConnPtr driver) +static bhyveMonitorPtr +bhyveMonitorOpenImpl(virDomainObjPtr vm, bhyveConnPtr driver) { - bhyveMonitorPtr mon = NULL; + bhyveMonitorPtr mon; struct kevent kev; - if (VIR_ALLOC(mon) < 0) + if (bhyveMonitorInitialize() < 0) + return NULL; + + if (!(mon = virObjectNew(bhyveMonitorClass))) return NULL; mon->driver = driver; + virObjectRef(vm); + mon->vm = vm; + mon->kq = kqueue(); if (mon->kq < 0) { virReportError(VIR_ERR_SYSTEM_ERROR, "%s", @@ -150,14 +197,7 @@ bhyveMonitorOpen(virDomainObjPtr vm, bhyveConnPtr driver) goto cleanup; } - mon->watch = virEventAddHandle(mon->kq, - VIR_EVENT_HANDLE_READABLE | - VIR_EVENT_HANDLE_ERROR | - VIR_EVENT_HANDLE_HANGUP, - bhyveMonitorIO, - vm, - bhyveMonitorRelease); - if (mon->watch < 0) { + if (!bhyveMonitorRegister(mon)) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("unable to register monitor events")); goto cleanup; @@ -166,18 +206,30 @@ bhyveMonitorOpen(virDomainObjPtr vm, bhyveConnPtr driver) return mon; cleanup: - bhyveMonitorRelease(mon); + bhyveMonitorClose(mon); return NULL; } +bhyveMonitorPtr +bhyveMonitorOpen(virDomainObjPtr vm, bhyveConnPtr driver) +{ + bhyveMonitorPtr mon; + + virObjectRef(vm); + mon = bhyveMonitorOpenImpl(vm, driver); + virObjectUnref(vm); + + return mon; +} + void bhyveMonitorClose(bhyveMonitorPtr mon) { if (mon == NULL) return; - if (mon->watch > 0) - virEventRemoveHandle(mon->watch); - else - bhyveMonitorRelease(mon); + VIR_DEBUG("cleaning up bhyveMonitor %p", mon); + + bhyveMonitorUnregister(mon); + virObjectUnref(mon); } -- 2.23.0 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list