diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c index 602edbe37968fadda46d655937dde17122b9370a..452566cc3f87a33aa9b87f01916fae8a8a8a12fa 100644 --- a/daemon/libvirtd.c +++ b/daemon/libvirtd.c @@ -893,8 +893,7 @@ static struct qemud_server *qemudInitialize(void) { return NULL; } - if (virEventPollInit() < 0) { - VIR_ERROR0(_("Failed to initialize event system")); + if (virEventRegisterDefaultImpl() < 0) { virMutexDestroy(&server->lock); if (virCondDestroy(&server->job) < 0) {} @@ -957,13 +956,6 @@ static struct qemud_server *qemudInitialize(void) { # endif #endif - virEventRegisterImpl(virEventPollAddHandle, - virEventPollUpdateHandle, - virEventPollRemoveHandle, - virEventPollAddTimeout, - virEventPollUpdateTimeout, - virEventPollRemoveTimeout); - return server; } @@ -2283,7 +2275,7 @@ qemudDispatchServerEvent(int watch, int fd, int events, void *opaque) { static int qemudOneLoop(void) { sig_atomic_t errors; - if (virEventPollRunOnce() < 0) + if (virEventRunDefaultImpl() < 0) return -1; /* Check for any signal handling errors and log them. */ diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 5dfb752176e613cbc9f45dda0a27898bc6a9e827..618b350c35d6d2b072dc01d46b34e101d6dcce5f 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -1768,6 +1768,9 @@ void virEventRegisterImpl(virEventAddHandleFunc addHandle, virEventUpdateTimeoutFunc updateTimeout, virEventRemoveTimeoutFunc removeTimeout); +int virEventRegisterDefaultImpl(void); +int virEventRunDefaultImpl(void); + /* * Secret manipulation API */ diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index 5962dbfee5ea6d6a20964107e8062e4e03fc4222..6b8c789541ce89c17b1ec21f0811ecaf807e95c0 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -79,6 +79,7 @@ typedef enum { VIR_FROM_SYSINFO = 37, /* Error from sysinfo/SMBIOS */ VIR_FROM_STREAMS = 38, /* Error from I/O streams */ VIR_FROM_VMWARE = 39, /* Error from VMware driver */ + VIR_FROM_EVENT = 40, /* Error from event loop impl */ } virErrorDomain; diff --git a/po/POTFILES.in b/po/POTFILES.in index 9852f97d7a69660dd7f560b2b459b2a585dd4f0c..1ed276507ea0a1577cdc3296a09c2e8ad4db1ac2 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -88,6 +88,7 @@ src/util/cgroup.c src/util/command.c src/util/conf.c src/util/dnsmasq.c +src/util/event_poll.c src/util/hooks.c src/util/hostusb.c src/util/interface.c diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 07810eacc008f47cc5136e90753f0f3342aa20ab..efcf3c5ec03f5f7fb29c53fd6285abcd5fbdd516 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -396,14 +396,6 @@ virEventUpdateTimeout; # event_poll.h virEventPollToNativeEvents; virEventPollFromNativeEvents; -virEventPollRunOnce; -virEventPollInit; -virEventPollRemoveTimeout; -virEventPollUpdateTimeout; -virEventPollAddTimeout; -virEventPollRemoveHandle; -virEventPollUpdateHandle; -virEventPollAddHandle; # fdstream.h diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 1a45be142027cc242bb76877d4865094341ece9c..cca8d085e763e485e68119b436fda7b70ae8ca15 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -424,4 +424,10 @@ LIBVIRT_0.8.8 { virConnectGetSysinfo; } LIBVIRT_0.8.6; +LIBVIRT_0.9.0 { + global: + virEventRegisterDefaultImpl; + virEventRunDefaultImpl; +} LIBVIRT_0.8.8; + # .... define new API here using predicted next version number .... diff --git a/src/util/event.c b/src/util/event.c index 680fef91318386ffb37e708f643f5679ee4209fe..0d88b557b62191d6748cde5268eab2f606231f4d 100644 --- a/src/util/event.c +++ b/src/util/event.c @@ -24,6 +24,9 @@ #include #include "event.h" +#include "event_poll.h" +#include "logging.h" +#include "virterror_internal.h" #include @@ -77,6 +80,15 @@ int virEventRemoveTimeout(int timer) { return removeTimeoutImpl(timer); } + +/***************************************************** + * + * Below this point are 3 *PUBLIC* APIs for event + * loop integration with applications using libvirt. + * These API contracts cannot be changed. + * + *****************************************************/ + /** * virEventRegisterImpl: * @addHandle: the callback to add fd handles @@ -86,14 +98,28 @@ int virEventRemoveTimeout(int timer) { * @updateTimeout: the callback to update a timeout * @removeTimeout: the callback to remove a timeout * - * Registers an event implementation + * Registers an event implementation, to allow integration + * with an external event loop. Applications would use this + * to integrate with the libglib2 event loop, or libevent + * or the QT event loop. + * + * If an application does not need to integrate with an + * existing event loop implementation, then the + * virEventRegisterDefaultImpl method can be used to setup + * the generic libvirt implementation. */ void virEventRegisterImpl(virEventAddHandleFunc addHandle, virEventUpdateHandleFunc updateHandle, virEventRemoveHandleFunc removeHandle, virEventAddTimeoutFunc addTimeout, virEventUpdateTimeoutFunc updateTimeout, - virEventRemoveTimeoutFunc removeTimeout) { + virEventRemoveTimeoutFunc removeTimeout) +{ + VIR_DEBUG("addHandle=%p updateHandle=%p removeHandle=%p " + "addTimeout=%p updateTimeout=%p removeTimeout=%p", + addHandle, updateHandle, removeHandle, + addTimeout, updateTimeout, removeTimeout); + addHandleImpl = addHandle; updateHandleImpl = updateHandle; removeHandleImpl = removeHandle; @@ -101,3 +127,67 @@ void virEventRegisterImpl(virEventAddHandleFunc addHandle, updateTimeoutImpl = updateTimeout; removeTimeoutImpl = removeTimeout; } + +/** + * 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 + */ +int virEventRegisterDefaultImpl(void) +{ + VIR_DEBUG0(""); + + virResetLastError(); + + if (virEventPollInit() < 0) { + virDispatchError(NULL); + return -1; + } + + virEventRegisterImpl( + virEventPollAddHandle, + virEventPollUpdateHandle, + virEventPollRemoveHandle, + virEventPollAddTimeout, + virEventPollUpdateTimeout, + virEventPollRemoveTimeout + ); + + return 0; +} + + +/** + * virEventRunDefaultImpl: + * + * Run one iteration of the event loop. Applications + * will generally want to have a thread which invokes + * this method in an infinite loop + * + * static bool quit = false; + * + * while (!quit) { + * if (virEventRunDefaultImpl() < 0) + * ...print error... + * } + */ +int virEventRunDefaultImpl(void) +{ + VIR_DEBUG0(""); + virResetLastError(); + + if (virEventPollRunOnce() < 0) { + virDispatchError(NULL); + return -1; + } + + return 0; +} diff --git a/src/util/event_poll.c b/src/util/event_poll.c index 13628409cd9e6dccd4f1551a32c659f30c385ac0..dd83fc34a8698683cc8db838fe68fa1486a8681d 100644 --- a/src/util/event_poll.c +++ b/src/util/event_poll.c @@ -36,9 +36,16 @@ #include "memory.h" #include "util.h" #include "ignore-value.h" +#include "virterror_internal.h" #define EVENT_DEBUG(fmt, ...) VIR_DEBUG(fmt, __VA_ARGS__) +#define VIR_FROM_THIS VIR_FROM_EVENT + +#define virEventError(code, ...) \ + virReportErrorHelper(NULL, VIR_FROM_EVENT, code, __FILE__, \ + __FUNCTION__, __LINE__, __VA_ARGS__) + static int virEventPollInterruptLocked(void); /* State for a single file handle being monitored */ @@ -316,6 +323,8 @@ static int virEventPollCalculateTimeout(int *timeout) { struct timeval tv; if (gettimeofday(&tv, NULL) < 0) { + virReportSystemError(errno, "%s", + _("Unable to get current time")); return -1; } @@ -350,8 +359,10 @@ static struct pollfd *virEventPollMakePollFDs(int *nfds) { } /* Setup the poll file handle data structs */ - if (VIR_ALLOC_N(fds, *nfds) < 0) + if (VIR_ALLOC_N(fds, *nfds) < 0) { + virReportOOMError(); return NULL; + } *nfds = 0; for (i = 0 ; i < eventLoop.handlesCount ; i++) { @@ -393,6 +404,8 @@ static int virEventPollDispatchTimeouts(void) { VIR_DEBUG("Dispatch %d", ntimeouts); if (gettimeofday(&tv, NULL) < 0) { + virReportSystemError(errno, "%s", + _("Unable to get current time")); return -1; } now = (((unsigned long long)tv.tv_sec)*1000) + @@ -584,6 +597,8 @@ int virEventPollRunOnce(void) { if (errno == EINTR) { goto retry; } + virReportSystemError(errno, "%s", + _("Unable to poll on file handles")); goto error_unlocked; } EVENT_DEBUG("Poll got %d event(s)", ret); @@ -626,6 +641,8 @@ static void virEventPollHandleWakeup(int watch ATTRIBUTE_UNUSED, int virEventPollInit(void) { if (virMutexInit(&eventLoop.lock) < 0) { + virReportSystemError(errno, "%s", + _("Unable to initialize mutex")); return -1; } @@ -634,12 +651,17 @@ int virEventPollInit(void) virSetNonBlock(eventLoop.wakeupfd[1]) < 0 || virSetCloseExec(eventLoop.wakeupfd[0]) < 0 || virSetCloseExec(eventLoop.wakeupfd[1]) < 0) { + virReportSystemError(errno, "%s", + _("Unable to setup wakeup pipe")); return -1; } if (virEventPollAddHandle(eventLoop.wakeupfd[0], VIR_EVENT_HANDLE_READABLE, virEventPollHandleWakeup, NULL, NULL) < 0) { + virEventError(VIR_ERR_INTERNAL_ERROR, + _("Unable to add handle %d to event loop"), + eventLoop.wakeupfd[0]); return -1; } diff --git a/src/util/virterror.c b/src/util/virterror.c index 89bb2a5acaa3cee6ba74a4efea165299a663c36b..aaa37206c2d9fbf968a417a51e97714763d0369e 100644 --- a/src/util/virterror.c +++ b/src/util/virterror.c @@ -200,6 +200,9 @@ static const char *virErrorDomainName(virErrorDomain domain) { case VIR_FROM_STREAMS: dom = "Streams "; break; + case VIR_FROM_EVENT: + dom = "Events "; + break; } return(dom); } diff --git a/tools/console.c b/tools/console.c index 84c28a3792cb8eb4341426229506ae4420d39f72..b9dd26832d6f9e92d02aa1ff8ff34d7317297b62 100644 --- a/tools/console.c +++ b/tools/console.c @@ -44,7 +44,6 @@ # include "virterror_internal.h" # include "event.h" -# include "event_poll.h" /* ie Ctrl-] as per telnet */ # define CTRL_CLOSE_BRACKET '\35' @@ -350,7 +349,7 @@ int vshRunConsole(virDomainPtr dom, const char *devname) NULL); while (!con->quit) { - if (virEventPollRunOnce() < 0) + if (virEventRunDefaultImpl() < 0) break; } diff --git a/tools/virsh.c b/tools/virsh.c index 95bcfcc987d888430963c40a41d2bf2d8ee034ad..f3754d74330c7739c728f76e33b252fcd341dd1a 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -11677,13 +11677,8 @@ vshInit(vshControl *ctl) /* set up the signals handlers to catch disconnections */ vshSetupSignals(); - virEventRegisterImpl(virEventPollAddHandle, - virEventPollUpdateHandle, - virEventPollRemoveHandle, - virEventPollAddTimeout, - virEventPollUpdateTimeout, - virEventPollRemoveTimeout); - virEventPollInit(); + if (virEventRegisterDefaultImpl() < 0) + return FALSE; ctl->conn = virConnectOpenAuth(ctl->name, virConnectAuthPtrDefault,