static int bhyveDomainDestroy(virDomainPtr dom) { bhyveConnPtr privconn = dom->conn->privateData; virDomainObjPtr vm; int ret = -1; if (!(vm = bhyveDomObjFromDomain(dom))) goto cleanup; if (virDomainDestroyEnsureACL(dom->conn, vm->def) < 0) goto cleanup; if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); goto cleanup; } ret = virBhyveProcessStop(privconn, vm, VIR_DOMAIN_SHUTOFF_DESTROYED); if (!vm->persistent) { virDomainObjListRemove(privconn->domains, vm); vm = NULL; } cleanup: if (vm) virObjectUnlock(vm); return ret; }
static void bhyveMonitorIO(int watch, int kq, int events ATTRIBUTE_UNUSED, void *opaque) { const struct timespec zerowait = { 0, 0 }; virDomainObjPtr vm = opaque; bhyveDomainObjPrivatePtr priv = vm->privateData; bhyveMonitorPtr mon = priv->mon; struct kevent kev; int rc, status; if (watch != mon->watch || kq != mon->kq) { virReportError(VIR_ERR_INTERNAL_ERROR, _("event from unexpected fd %d!=%d / watch %d!=%d"), mon->kq, kq, mon->watch, watch); return; } rc = kevent(kq, NULL, 0, &kev, 1, &zerowait); if (rc < 0) { virReportSystemError(errno, "%s", _("Unable to query kqueue")); return; } if (rc == 0) return; if ((kev.flags & EV_ERROR) != 0) { virReportSystemError(kev.data, "%s", _("Unable to query kqueue")); 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 %ju!=%ju"), (uintmax_t)vm->pid, (uintmax_t)kev.ident); return; } 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); } 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); } 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); } 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); } } } }