/** * virEventRegisterDefaultImpl: * * Registers a default event implementation based on the * poll() system call. This is a generic implementation * that can be used by any client application which does * not have a need to integrate with an external event * loop impl. * * Once registered, the application can invoke * virEventRunDefaultImpl in a loop to process * events * * Returns 0 on success, -1 on failure. */ int virEventRegisterDefaultImpl(void) { VIR_DEBUG("registering default event implementation"); virResetLastError(); if (virEventPollInit() < 0) { virDispatchError(NULL); return -1; } virEventRegisterImpl( virEventPollAddHandle, virEventPollUpdateHandle, virEventPollRemoveHandle, virEventPollAddTimeout, virEventPollUpdateTimeout, virEventPollRemoveTimeout ); return 0; }
static void * event_thread(void *arg) { struct event_args *args = (struct event_args *)arg; virConnectPtr dconn = NULL; int callback1ret = -1; int sts; dbg_printf(3, "Libvirt event listener starting\n"); if (args->uri) dbg_printf(3," * URI: %s\n", args->uri); if (args->path) dbg_printf(3," * Socket path: %s\n", args->path); dbg_printf(3," * Mode: %s\n", args->mode ? "VMChannel" : "Serial"); top: virEventRegisterImpl(myEventAddHandleFunc, myEventUpdateHandleFunc, myEventRemoveHandleFunc, myEventAddTimeoutFunc, myEventUpdateTimeoutFunc, myEventRemoveTimeoutFunc); dconn = virConnectOpen(args->uri); if (!dconn) { dbg_printf(1, "Error connecting to libvirt\n"); goto out; } DEBUG0("Registering domain event cbs"); registerExisting(dconn, args->path, args->mode); callback1ret = virConnectDomainEventRegister(dconn, myDomainEventCallback1, arg, NULL); if (callback1ret == 0) { while (run) { struct pollfd pfd = { .fd = h_fd, .events = h_event, .revents = 0 }; sts = poll(&pfd, 1, TIMEOUT_MS); /* We are assuming timeout of 0 here - so execute every time */ if (t_cb && t_active) { t_cb(t_timeout, t_opaque); } if (sts == 0) { /* DEBUG0("Poll timeout"); */ continue; } if (sts < 0) { DEBUG0("Poll failed"); continue; } if (pfd.revents & POLLHUP) { DEBUG0("Reset by peer"); virConnectDomainEventDeregister(dconn, myDomainEventCallback1); if (dconn && virConnectClose(dconn) < 0) dbg_printf(1, "error closing libvirt connection\n"); DEBUG0("Attempting to reinitialize libvirt connection"); goto top; } if (h_cb) { h_cb(0, h_fd, myPollEventToEventHandleType(pfd.revents & h_event), h_opaque); } } DEBUG0("Deregistering event handlers"); virConnectDomainEventDeregister(dconn, myDomainEventCallback1); } DEBUG0("Closing connection"); if (dconn && virConnectClose(dconn) < 0) { dbg_printf(1, "error closing libvirt connection\n"); } out: free(args->uri); free(args->path); free(args); return NULL; } int start_event_listener(const char *uri, const char *path, int mode, int *wake_fd) { struct event_args *args = NULL; int wake_pipe[2]; virInitialize(); args = malloc(sizeof(*args)); if (!args) return -1; memset(args, 0, sizeof(*args)); if (pipe2(wake_pipe, O_CLOEXEC) < 0) { goto out_fail; } if (uri) { args->uri = strdup(uri); if (args->uri == NULL) goto out_fail; } if (path) { args->path = strdup(path); if (args->path == NULL) goto out_fail; } args->mode = mode; //args->p_tid = pthread_self(); *wake_fd = wake_pipe[0]; args->wake_fd = wake_pipe[1]; run = 1; return pthread_create(&event_tid, NULL, event_thread, args); out_fail: free(args->uri); free(args->path); free(args); return -1; } int stop_event_listener(void) { run = 0; //pthread_cancel(event_tid); pthread_join(event_tid, NULL); event_tid = 0; return 0; }