[libvirt] PATCH: Change signature of virEventAddHandle to allow multiple calls per FD
Ben Guthro
bguthro at virtualiron.com
Mon Nov 17 17:33:09 UTC 2008
well, that was a lot of fallout.
All looks necessary though.
+1 from me
Daniel P. Berrange wrote on 11/17/2008 11:58 AM:
> As discussed previously, this patch changes the semantics of the public
> API for dealing with file handle watches. Previously we would track the
> watch based on the file handle number directly. With this change, the
> virEventAddHandle method returns an integer 'watch' number. This watch
> number is required when unregistering or updating a watch. The watch is
> also passed into the callback when an event occurrs. This allows for
> multiple watches to be registered against the same file descriptor.
>
> There was quite alot of fallout from this patch requiring many callers
> to be updated to comply with the new semantics.
>
> examples/domain-events/events-c/event-test.c | 7 +-
> examples/domain-events/events-python/event-test.py | 12 ++--
> include/libvirt/libvirt.h | 20 ++++---
> include/libvirt/libvirt.h.in | 20 ++++---
> python/libvir.c | 8 +-
> qemud/event.c | 27 ++++++---
> qemud/event.h | 10 +--
> qemud/mdns.c | 16 +++--
> qemud/qemud.c | 59 +++++++++++----------
> qemud/qemud.h | 2
> src/domain_conf.h | 3 +
> src/event.c | 8 +-
> src/event.h | 8 +-
> src/lxc_driver.c | 25 +++++---
> src/qemu_driver.c | 43 ++++++++-------
> src/remote_internal.c | 27 ++++++---
> 16 files changed, 176 insertions(+), 119 deletions(-)
>
>
> Daniel
>
> diff --git a/examples/domain-events/events-c/event-test.c b/examples/domain-events/events-c/event-test.c
> --- a/examples/domain-events/events-c/event-test.c
> +++ b/examples/domain-events/events-c/event-test.c
> @@ -40,8 +40,8 @@ int myDomainEventCallback2 (virConnectPt
> int event, int detail, void *opaque);
> int myEventAddHandleFunc (int fd, int event,
> virEventHandleCallback cb, void *opaque);
> -void myEventUpdateHandleFunc(int fd, int event);
> -int myEventRemoveHandleFunc(int fd);
> +void myEventUpdateHandleFunc(int watch, int event);
> +int myEventRemoveHandleFunc(int watch);
>
> int myEventAddTimeoutFunc(int timeout, virEventTimeoutCallback cb,
> void *opaque);
> @@ -308,7 +308,8 @@ int main(int argc, char **argv)
> }
>
> if(h_cb) {
> - h_cb(h_fd,
> + h_cb(0,
> + h_fd,
> myPollEventToEventHandleType(pfd.revents & h_event),
> h_opaque);
> }
> diff --git a/examples/domain-events/events-python/event-test.py b/examples/domain-events/events-python/event-test.py
> --- a/examples/domain-events/events-python/event-test.py
> +++ b/examples/domain-events/events-python/event-test.py
> @@ -75,19 +75,19 @@ def myAddHandle(fd, events, cb, opaque):
>
> mypoll.register(fd, myEventHandleTypeToPollEvent(events))
>
> -def myUpdateHandle(fd, event):
> +def myUpdateHandle(watch, event):
> global h_fd, h_events
> #print "Updating Handle %s %s" % (str(fd), str(events))
> h_fd = fd
> h_events = event
> - mypoll.unregister(fd)
> - mypoll.register(fd, myEventHandleTypeToPollEvent(event))
> + mypoll.unregister(watch)
> + mypoll.register(watch, myEventHandleTypeToPollEvent(event))
>
> -def myRemoveHandle(fd):
> +def myRemoveHandle(watch):
> global h_fd
> #print "Removing Handle %s" % str(fd)
> h_fd = 0
> - mypoll.unregister(fd)
> + mypoll.unregister(watch)
>
> def myAddTimeout(timeout, cb, opaque):
> global t_active, t_timeout, t_cb, t_opaque
> @@ -175,7 +175,7 @@ def main():
>
> if h_cb != None:
> #print "Invoking Handle CB"
> - h_cb(h_fd, myPollEventToEventHandleType(revents & h_events),
> + h_cb(0, h_fd, myPollEventToEventHandleType(revents & h_events),
> h_opaque[0], h_opaque[1])
>
> #print "DEBUG EXIT"
> diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h
> --- a/include/libvirt/libvirt.h
> +++ b/include/libvirt/libvirt.h
> @@ -1121,13 +1121,15 @@ typedef enum {
> /**
> * virEventHandleCallback:
> *
> + * @watch: watch on which the event occurred
> * @fd: file handle on which the event occurred
> * @events: bitset of events from virEventHandleType constants
> * @opaque: user data registered with handle
> *
> - * callback for receiving file handle events
> + * Callback for receiving file handle events. The callback will
> + * be invoked once for each event which is pending.
> */
> -typedef void (*virEventHandleCallback)(int fd, int events, void *opaque);
> +typedef void (*virEventHandleCallback)(int watch, int fd, int events, void *opaque);
>
> /**
> * virEventAddHandleFunc:
> @@ -1137,29 +1139,33 @@ typedef void (*virEventHandleCallback)(i
> * @opaque: user data to pass to the callback
> *
> * Part of the EventImpl, this callback Adds a file handle callback to
> - * listen for specific events
> + * listen for specific events. The same file handle can be registered
> + * multiple times provided the requested event sets are non-overlapping
> + *
> + * Returns a handle watch number to be used for updating
> + * and unregistering for events
> */
> typedef int (*virEventAddHandleFunc)(int fd, int event,
> virEventHandleCallback cb, void *opaque);
>
> /**
> * virEventUpdateHandleFunc:
> - * @fd: file descriptor to modify
> + * @watch: file descriptor watch to modify
> * @event: new events to listen on
> *
> * Part of the EventImpl, this user-provided callback is notified when
> * events to listen on change
> */
> -typedef void (*virEventUpdateHandleFunc)(int fd, int event);
> +typedef void (*virEventUpdateHandleFunc)(int watch, int event);
>
> /**
> * virEventRemoveHandleFunc:
> - * @fd: file descriptor to stop listening on
> + * @watch: file descriptor watch to stop listening on
> *
> * Part of the EventImpl, this user-provided callback is notified when
> * an fd is no longer being listened on
> */
> -typedef int (*virEventRemoveHandleFunc)(int fd);
> +typedef int (*virEventRemoveHandleFunc)(int watch);
>
> /**
> * virEventTimeoutCallback:
> diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
> --- a/include/libvirt/libvirt.h.in
> +++ b/include/libvirt/libvirt.h.in
> @@ -1121,13 +1121,15 @@ typedef enum {
> /**
> * virEventHandleCallback:
> *
> + * @watch: watch on which the event occurred
> * @fd: file handle on which the event occurred
> * @events: bitset of events from virEventHandleType constants
> * @opaque: user data registered with handle
> *
> - * callback for receiving file handle events
> + * Callback for receiving file handle events. The callback will
> + * be invoked once for each event which is pending.
> */
> -typedef void (*virEventHandleCallback)(int fd, int events, void *opaque);
> +typedef void (*virEventHandleCallback)(int watch, int fd, int events, void *opaque);
>
> /**
> * virEventAddHandleFunc:
> @@ -1137,29 +1139,33 @@ typedef void (*virEventHandleCallback)(i
> * @opaque: user data to pass to the callback
> *
> * Part of the EventImpl, this callback Adds a file handle callback to
> - * listen for specific events
> + * listen for specific events. The same file handle can be registered
> + * multiple times provided the requested event sets are non-overlapping
> + *
> + * Returns a handle watch number to be used for updating
> + * and unregistering for events
> */
> typedef int (*virEventAddHandleFunc)(int fd, int event,
> virEventHandleCallback cb, void *opaque);
>
> /**
> * virEventUpdateHandleFunc:
> - * @fd: file descriptor to modify
> + * @watch: file descriptor watch to modify
> * @event: new events to listen on
> *
> * Part of the EventImpl, this user-provided callback is notified when
> * events to listen on change
> */
> -typedef void (*virEventUpdateHandleFunc)(int fd, int event);
> +typedef void (*virEventUpdateHandleFunc)(int watch, int event);
>
> /**
> * virEventRemoveHandleFunc:
> - * @fd: file descriptor to stop listening on
> + * @watch: file descriptor watch to stop listening on
> *
> * Part of the EventImpl, this user-provided callback is notified when
> * an fd is no longer being listened on
> */
> -typedef int (*virEventRemoveHandleFunc)(int fd);
> +typedef int (*virEventRemoveHandleFunc)(int watch);
>
> /**
> * virEventTimeoutCallback:
> diff --git a/python/libvir.c b/python/libvir.c
> --- a/python/libvir.c
> +++ b/python/libvir.c
> @@ -1940,15 +1940,15 @@ libvirt_virEventInvokeHandleCallback(PyO
> libvirt_virEventInvokeHandleCallback(PyObject *self ATTRIBUTE_UNUSED,
> PyObject *args)
> {
> - int fd, event;
> + int watch, fd, event;
> PyObject *py_f;
> PyObject *py_opaque;
> virEventHandleCallback cb;
> void *opaque;
>
> if (!PyArg_ParseTuple
> - (args, (char *) "iiOO:virEventInvokeHandleCallback",
> - &fd, &event, &py_f, &py_opaque
> + (args, (char *) "iiiOO:virEventInvokeHandleCallback",
> + &watch, &fd, &event, &py_f, &py_opaque
> ))
> return VIR_PY_INT_FAIL;
>
> @@ -1956,7 +1956,7 @@ libvirt_virEventInvokeHandleCallback(PyO
> opaque = (void *) PyvirVoidPtr_Get(py_opaque);
>
> if(cb)
> - cb (fd, event, opaque);
> + cb (watch, fd, event, opaque);
>
> return VIR_PY_INT_SUCCESS;
> }
> diff --git a/qemud/event.c b/qemud/event.c
> --- a/qemud/event.c
> +++ b/qemud/event.c
> @@ -37,6 +37,7 @@
>
> /* State for a single file handle being monitored */
> struct virEventHandle {
> + int watch;
> int fd;
> int events;
> virEventHandleCallback cb;
> @@ -71,6 +72,9 @@ struct virEventLoop {
> /* Only have one event loop */
> static struct virEventLoop eventLoop;
>
> +/* Unique ID for the next FD watch to be registered */
> +static int nextWatch = 0;
> +
> /* Unique ID for the next timer to be registered */
> static int nextTimer = 0;
>
> @@ -91,6 +95,7 @@ int virEventAddHandleImpl(int fd, int ev
> eventLoop.handlesAlloc += EVENT_ALLOC_EXTENT;
> }
>
> + eventLoop.handles[eventLoop.handlesCount].watch = nextWatch++;
> eventLoop.handles[eventLoop.handlesCount].fd = fd;
> eventLoop.handles[eventLoop.handlesCount].events =
> virEventHandleTypeToPollEvent(events);
> @@ -100,13 +105,13 @@ int virEventAddHandleImpl(int fd, int ev
>
> eventLoop.handlesCount++;
>
> - return 0;
> + return nextWatch-1;
> }
>
> -void virEventUpdateHandleImpl(int fd, int events) {
> +void virEventUpdateHandleImpl(int watch, int events) {
> int i;
> for (i = 0 ; i < eventLoop.handlesCount ; i++) {
> - if (eventLoop.handles[i].fd == fd) {
> + if (eventLoop.handles[i].watch == watch) {
> eventLoop.handles[i].events =
> virEventHandleTypeToPollEvent(events);
> break;
> @@ -120,15 +125,15 @@ void virEventUpdateHandleImpl(int fd, in
> * For this reason we only ever set a flag in the existing list.
> * Actual deletion will be done out-of-band
> */
> -int virEventRemoveHandleImpl(int fd) {
> +int virEventRemoveHandleImpl(int watch) {
> int i;
> - EVENT_DEBUG("Remove handle %d", fd);
> + EVENT_DEBUG("Remove handle %d", watch);
> for (i = 0 ; i < eventLoop.handlesCount ; i++) {
> if (eventLoop.handles[i].deleted)
> continue;
>
> - if (eventLoop.handles[i].fd == fd) {
> - EVENT_DEBUG("mark delete %d", i);
> + if (eventLoop.handles[i].watch == watch) {
> + EVENT_DEBUG("mark delete %d %d", i, eventLoop.handles[i].fd);
> eventLoop.handles[i].deleted = 1;
> return 0;
> }
> @@ -356,9 +361,13 @@ static int virEventDispatchHandles(struc
>
> if (fds[i].revents) {
> hEvents = virPollEventToEventHandleType(fds[i].revents);
> - EVENT_DEBUG("Dispatch %d %d %p", fds[i].fd, fds[i].revents,
> + EVENT_DEBUG("Dispatch %d %d %d %p",
> + eventLoop.handles[i].watch,
> + fds[i].fd, fds[i].revents,
> eventLoop.handles[i].opaque);
> - (eventLoop.handles[i].cb)(fds[i].fd, hEvents,
> + (eventLoop.handles[i].cb)(eventLoop.handles[i].watch,
> + fds[i].fd,
> + hEvents,
> eventLoop.handles[i].opaque);
> }
> }
> diff --git a/qemud/event.h b/qemud/event.h
> --- a/qemud/event.h
> +++ b/qemud/event.h
> @@ -24,7 +24,7 @@
> #ifndef __VIRTD_EVENT_H__
> #define __VIRTD_EVENT_H__
>
> -#include "../src/event.h"
> +#include "internal.h"
>
> /**
> * virEventAddHandleImpl: register a callback for monitoring file handle events
> @@ -42,21 +42,21 @@ int virEventAddHandleImpl(int fd, int ev
> /**
> * virEventUpdateHandleImpl: change event set for a monitored file handle
> *
> - * @fd: file handle to monitor for events
> + * @watch: watch whose handle to update
> * @events: bitset of events to watch from POLLnnn constants
> *
> * Will not fail if fd exists
> */
> -void virEventUpdateHandleImpl(int fd, int events);
> +void virEventUpdateHandleImpl(int watch, int events);
>
> /**
> * virEventRemoveHandleImpl: unregister a callback from a file handle
> *
> - * @fd: file handle to stop monitoring for events
> + * @watch: watch whose handle to remove
> *
> * returns -1 if the file handle was not registered, 0 upon success
> */
> -int virEventRemoveHandleImpl(int fd);
> +int virEventRemoveHandleImpl(int watch);
>
> /**
> * virEventAddTimeoutImpl: register a callback for a timer event
> diff --git a/qemud/mdns.c b/qemud/mdns.c
> --- a/qemud/mdns.c
> +++ b/qemud/mdns.c
> @@ -68,6 +68,7 @@ struct libvirtd_mdns {
>
> /* Avahi API requires this struct names in the app :-( */
> struct AvahiWatch {
> + int watch;
> int fd;
> int revents;
> AvahiWatchCallback callback;
> @@ -228,17 +229,18 @@ static void libvirtd_mdns_client_callbac
> }
>
>
> -static void libvirtd_mdns_watch_dispatch(int fd, int events, void *opaque)
> +static void libvirtd_mdns_watch_dispatch(int watch, int fd, int events, void *opaque)
> {
> AvahiWatch *w = (AvahiWatch*)opaque;
> int fd_events = virEventHandleTypeToPollEvent(events);
> - AVAHI_DEBUG("Dispatch watch FD %d Event %d", fd, fd_events);
> + AVAHI_DEBUG("Dispatch watch %d FD %d Event %d", watch, fd, fd_events);
> w->revents = fd_events;
> w->callback(w, fd, fd_events, w->userdata);
> }
>
> static AvahiWatch *libvirtd_mdns_watch_new(const AvahiPoll *api ATTRIBUTE_UNUSED,
> - int fd, AvahiWatchEvent event, AvahiWatchCallback cb, void *userdata) {
> + int fd, AvahiWatchEvent event,
> + AvahiWatchCallback cb, void *userdata) {
> AvahiWatch *w;
> virEventHandleType hEvents;
> if (VIR_ALLOC(w) < 0)
> @@ -251,8 +253,8 @@ static AvahiWatch *libvirtd_mdns_watch_n
>
> AVAHI_DEBUG("New handle %p FD %d Event %d", w, w->fd, event);
> hEvents = virPollEventToEventHandleType(event);
> - if (virEventAddHandleImpl(fd, hEvents,
> - libvirtd_mdns_watch_dispatch, w) < 0) {
> + if ((w->watch = virEventAddHandleImpl(fd, hEvents,
> + libvirtd_mdns_watch_dispatch, w)) < 0) {
> VIR_FREE(w);
> return NULL;
> }
> @@ -263,7 +265,7 @@ static void libvirtd_mdns_watch_update(A
> static void libvirtd_mdns_watch_update(AvahiWatch *w, AvahiWatchEvent event)
> {
> AVAHI_DEBUG("Update handle %p FD %d Event %d", w, w->fd, event);
> - virEventUpdateHandleImpl(w->fd, event);
> + virEventUpdateHandleImpl(w->watch, event);
> }
>
> static AvahiWatchEvent libvirtd_mdns_watch_get_events(AvahiWatch *w)
> @@ -275,7 +277,7 @@ static void libvirtd_mdns_watch_free(Ava
> static void libvirtd_mdns_watch_free(AvahiWatch *w)
> {
> AVAHI_DEBUG("Free handle %p %d", w, w->fd);
> - virEventRemoveHandleImpl(w->fd);
> + virEventRemoveHandleImpl(w->watch);
> VIR_FREE(w);
> }
>
> diff --git a/qemud/qemud.c b/qemud/qemud.c
> --- a/qemud/qemud.c
> +++ b/qemud/qemud.c
> @@ -142,8 +142,8 @@ static void sig_handler(int sig, siginfo
> errno = origerrno;
> }
>
> -static void qemudDispatchClientEvent(int fd, int events, void *opaque);
> -static void qemudDispatchServerEvent(int fd, int events, void *opaque);
> +static void qemudDispatchClientEvent(int watch, int fd, int events, void *opaque);
> +static void qemudDispatchServerEvent(int watch, int fd, int events, void *opaque);
> static int qemudRegisterClientEvent(struct qemud_server *server,
> struct qemud_client *client,
> int removeFirst);
> @@ -245,7 +245,8 @@ remoteInitializeGnuTLS (void)
> }
>
> static void
> -qemudDispatchSignalEvent(int fd ATTRIBUTE_UNUSED,
> +qemudDispatchSignalEvent(int watch ATTRIBUTE_UNUSED,
> + int fd ATTRIBUTE_UNUSED,
> int events ATTRIBUTE_UNUSED,
> void *opaque) {
> struct qemud_server *server = (struct qemud_server *)opaque;
> @@ -534,12 +535,12 @@ static int qemudListenUnix(struct qemud_
> goto cleanup;
> }
>
> - if (virEventAddHandleImpl(sock->fd,
> - VIR_EVENT_HANDLE_READABLE |
> - VIR_EVENT_HANDLE_ERROR |
> - VIR_EVENT_HANDLE_HANGUP,
> - qemudDispatchServerEvent,
> - server) < 0) {
> + if ((sock->watch = virEventAddHandleImpl(sock->fd,
> + VIR_EVENT_HANDLE_READABLE |
> + VIR_EVENT_HANDLE_ERROR |
> + VIR_EVENT_HANDLE_HANGUP,
> + qemudDispatchServerEvent,
> + server)) < 0) {
> qemudLog(QEMUD_ERR, "%s",
> _("Failed to add server event callback"));
> goto cleanup;
> @@ -666,12 +667,12 @@ remoteListenTCP (struct qemud_server *se
> goto cleanup;
> }
>
> - if (virEventAddHandleImpl(sock->fd,
> - VIR_EVENT_HANDLE_READABLE |
> - VIR_EVENT_HANDLE_ERROR |
> - VIR_EVENT_HANDLE_HANGUP,
> - qemudDispatchServerEvent,
> - server) < 0) {
> + if ((sock->watch = virEventAddHandleImpl(sock->fd,
> + VIR_EVENT_HANDLE_READABLE |
> + VIR_EVENT_HANDLE_ERROR |
> + VIR_EVENT_HANDLE_HANGUP,
> + qemudDispatchServerEvent,
> + server)) < 0) {
> qemudLog(QEMUD_ERR, "%s", _("Failed to add server event callback"));
> goto cleanup;
> }
> @@ -1232,7 +1233,7 @@ static void qemudDispatchClientFailure(s
> tmp = tmp->next;
> }
>
> - virEventRemoveHandleImpl(client->fd);
> + virEventRemoveHandleImpl(client->watch);
>
> /* Deregister event delivery callback */
> if(client->conn) {
> @@ -1596,18 +1597,21 @@ qemudDispatchClientWrite(struct qemud_se
>
>
> static void
> -qemudDispatchClientEvent(int fd, int events, void *opaque) {
> +qemudDispatchClientEvent(int watch, int fd, int events, void *opaque) {
> struct qemud_server *server = (struct qemud_server *)opaque;
> struct qemud_client *client = server->clients;
>
> while (client) {
> - if (client->fd == fd)
> + if (client->watch == watch)
> break;
>
> client = client->next;
> }
>
> if (!client)
> + return;
> +
> + if (client->fd != fd)
> return;
>
> if (events == VIR_EVENT_HANDLE_WRITABLE)
> @@ -1644,32 +1648,35 @@ static int qemudRegisterClientEvent(stru
> }
>
> if (removeFirst)
> - if (virEventRemoveHandleImpl(client->fd) < 0)
> + if (virEventRemoveHandleImpl(client->watch) < 0)
> return -1;
>
> - if (virEventAddHandleImpl(client->fd,
> - mode | VIR_EVENT_HANDLE_ERROR |
> - VIR_EVENT_HANDLE_HANGUP,
> - qemudDispatchClientEvent,
> - server) < 0)
> + if ((client->watch = virEventAddHandleImpl(client->fd,
> + mode | VIR_EVENT_HANDLE_ERROR |
> + VIR_EVENT_HANDLE_HANGUP,
> + qemudDispatchClientEvent,
> + server)) < 0)
> return -1;
>
> return 0;
> }
>
> static void
> -qemudDispatchServerEvent(int fd, int events, void *opaque) {
> +qemudDispatchServerEvent(int watch, int fd, int events, void *opaque) {
> struct qemud_server *server = (struct qemud_server *)opaque;
> struct qemud_socket *sock = server->sockets;
>
> while (sock) {
> - if (sock->fd == fd)
> + if (sock->watch == watch)
> break;
>
> sock = sock->next;
> }
>
> if (!sock)
> + return;
> +
> + if (sock->fd != fd)
> return;
>
> if (events)
> diff --git a/qemud/qemud.h b/qemud/qemud.h
> --- a/qemud/qemud.h
> +++ b/qemud/qemud.h
> @@ -96,6 +96,7 @@ struct qemud_client {
> int magic;
>
> int fd;
> + int watch;
> int readonly;
> enum qemud_mode mode;
>
> @@ -141,6 +142,7 @@ struct qemud_client {
>
> struct qemud_socket {
> int fd;
> + int watch;
> int readonly;
> int type; /* qemud_sock_type */
> int auth;
> diff --git a/src/domain_conf.h b/src/domain_conf.h
> --- a/src/domain_conf.h
> +++ b/src/domain_conf.h
> @@ -455,8 +455,11 @@ struct _virDomainObj {
> struct _virDomainObj {
> int stdin_fd;
> int stdout_fd;
> + int stdout_watch;
> int stderr_fd;
> + int stderr_watch;
> int monitor;
> + int monitorWatch;
> int logfile;
> int pid;
> int state;
> diff --git a/src/event.c b/src/event.c
> --- a/src/event.c
> +++ b/src/event.c
> @@ -42,15 +42,15 @@ int virEventAddHandle(int fd, int events
> return addHandleImpl(fd, events, cb, opaque);
> }
>
> -void virEventUpdateHandle(int fd, int events) {
> - updateHandleImpl(fd, events);
> +void virEventUpdateHandle(int watch, int events) {
> + updateHandleImpl(watch, events);
> }
>
> -int virEventRemoveHandle(int fd) {
> +int virEventRemoveHandle(int watch) {
> if (!removeHandleImpl)
> return -1;
>
> - return removeHandleImpl(fd);
> + return removeHandleImpl(watch);
> }
>
> int virEventAddTimeout(int timeout, virEventTimeoutCallback cb, void *opaque) {
> diff --git a/src/event.h b/src/event.h
> --- a/src/event.h
> +++ b/src/event.h
> @@ -40,21 +40,21 @@ int virEventAddHandle(int fd, int events
> /**
> * virEventUpdateHandle: change event set for a monitored file handle
> *
> - * @fd: file handle to monitor for events
> + * @watch: watch whose file handle to update
> * @events: bitset of events to watch from virEventHandleType constants
> *
> * Will not fail if fd exists
> */
> -void virEventUpdateHandle(int fd, int events);
> +void virEventUpdateHandle(int watch, int events);
>
> /**
> * virEventRemoveHandle: unregister a callback from a file handle
> *
> - * @fd: file handle to stop monitoring for events
> + * @watch: watch whose file handle to remove
> *
> * returns -1 if the file handle was not registered, 0 upon success
> */
> -int virEventRemoveHandle(int fd);
> +int virEventRemoveHandle(int watch);
>
> /**
> * virEventAddTimeout: register a callback for a timer event
> diff --git a/src/lxc_driver.c b/src/lxc_driver.c
> --- a/src/lxc_driver.c
> +++ b/src/lxc_driver.c
> @@ -387,7 +387,7 @@ static int lxcVMCleanup(virConnectPtr co
> DEBUG("container exited with rc: %d", rc);
> }
>
> - virEventRemoveHandle(vm->monitor);
> + virEventRemoveHandle(vm->monitorWatch);
> close(vm->monitor);
>
> virFileDeletePid(driver->stateDir, vm->def->name);
> @@ -582,7 +582,8 @@ static int lxcVmTerminate(virConnectPtr
> return lxcVMCleanup(conn, driver, vm);
> }
>
> -static void lxcMonitorEvent(int fd,
> +static void lxcMonitorEvent(int watch,
> + int fd,
> int events ATTRIBUTE_UNUSED,
> void *data)
> {
> @@ -591,18 +592,23 @@ static void lxcMonitorEvent(int fd,
> unsigned int i;
>
> for (i = 0 ; i < driver->domains.count ; i++) {
> - if (driver->domains.objs[i]->monitor == fd) {
> + if (driver->domains.objs[i]->monitorWatch == watch) {
> vm = driver->domains.objs[i];
> break;
> }
> }
> if (!vm) {
> - virEventRemoveHandle(fd);
> + virEventRemoveHandle(watch);
> + return;
> + }
> +
> + if (vm->monitor != fd) {
> + virEventRemoveHandle(watch);
> return;
> }
>
> if (lxcVmTerminate(NULL, driver, vm, SIGINT) < 0)
> - virEventRemoveHandle(fd);
> + virEventRemoveHandle(watch);
> }
>
>
> @@ -810,10 +816,11 @@ static int lxcVmStart(virConnectPtr conn
> vm->def->id = vm->pid;
> vm->state = VIR_DOMAIN_RUNNING;
>
> - if (virEventAddHandle(vm->monitor,
> - VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_HANGUP,
> - lxcMonitorEvent,
> - driver) < 0) {
> + if ((vm->monitorWatch = virEventAddHandle(
> + vm->monitor,
> + VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_HANGUP,
> + lxcMonitorEvent,
> + driver)) < 0) {
> lxcVmTerminate(conn, driver, vm, 0);
> goto cleanup;
> }
> diff --git a/src/qemu_driver.c b/src/qemu_driver.c
> --- a/src/qemu_driver.c
> +++ b/src/qemu_driver.c
> @@ -110,7 +110,8 @@ static void qemudDomainEventDispatch (st
> int event,
> int detail);
>
> -static void qemudDispatchVMEvent(int fd,
> +static void qemudDispatchVMEvent(int watch,
> + int fd,
> int events,
> void *opaque);
>
> @@ -946,18 +947,18 @@ static int qemudStartVMDaemon(virConnect
> }
>
> if (ret == 0) {
> - if ((virEventAddHandle(vm->stdout_fd,
> - VIR_EVENT_HANDLE_READABLE |
> - VIR_EVENT_HANDLE_ERROR |
> - VIR_EVENT_HANDLE_HANGUP,
> - qemudDispatchVMEvent,
> - driver) < 0) ||
> - (virEventAddHandle(vm->stderr_fd,
> - VIR_EVENT_HANDLE_READABLE |
> - VIR_EVENT_HANDLE_ERROR |
> - VIR_EVENT_HANDLE_HANGUP,
> - qemudDispatchVMEvent,
> - driver) < 0) ||
> + if (((vm->stdout_watch = virEventAddHandle(vm->stdout_fd,
> + VIR_EVENT_HANDLE_READABLE |
> + VIR_EVENT_HANDLE_ERROR |
> + VIR_EVENT_HANDLE_HANGUP,
> + qemudDispatchVMEvent,
> + driver)) < 0) ||
> + ((vm->stderr_watch = virEventAddHandle(vm->stderr_fd,
> + VIR_EVENT_HANDLE_READABLE |
> + VIR_EVENT_HANDLE_ERROR |
> + VIR_EVENT_HANDLE_HANGUP,
> + qemudDispatchVMEvent,
> + driver)) < 0) ||
> (qemudWaitForMonitor(conn, driver, vm) < 0) ||
> (qemudDetectVcpuPIDs(conn, driver, vm) < 0) ||
> (qemudInitCpus(conn, driver, vm, migrateFrom) < 0)) {
> @@ -1008,8 +1009,8 @@ static void qemudShutdownVMDaemon(virCon
> qemudVMData(driver, vm, vm->stdout_fd);
> qemudVMData(driver, vm, vm->stderr_fd);
>
> - virEventRemoveHandle(vm->stdout_fd);
> - virEventRemoveHandle(vm->stderr_fd);
> + virEventRemoveHandle(vm->stdout_watch);
> + virEventRemoveHandle(vm->stderr_watch);
>
> if (close(vm->logfile) < 0)
> qemudLog(QEMUD_WARN, _("Unable to close logfile %d: %s\n"),
> @@ -1072,15 +1073,15 @@ static int qemudDispatchVMFailure(struct
>
>
> static void
> -qemudDispatchVMEvent(int fd, int events, void *opaque) {
> +qemudDispatchVMEvent(int watch, int fd, int events, void *opaque) {
> struct qemud_driver *driver = (struct qemud_driver *)opaque;
> virDomainObjPtr vm = NULL;
> unsigned int i;
>
> for (i = 0 ; i < driver->domains.count ; i++) {
> if (virDomainIsActive(driver->domains.objs[i]) &&
> - (driver->domains.objs[i]->stdout_fd == fd ||
> - driver->domains.objs[i]->stderr_fd == fd)) {
> + (driver->domains.objs[i]->stdout_watch == watch ||
> + driver->domains.objs[i]->stderr_watch == watch)) {
> vm = driver->domains.objs[i];
> break;
> }
> @@ -1088,6 +1089,12 @@ qemudDispatchVMEvent(int fd, int events,
>
> if (!vm)
> return;
> +
> + if (vm->stdout_fd != fd &&
> + vm->stderr_fd != fd) {
> + qemudDispatchVMFailure(driver, vm, fd);
> + return;
> + }
>
> if (events == VIR_EVENT_HANDLE_READABLE)
> qemudDispatchVMLog(driver, vm, fd);
> diff --git a/src/remote_internal.c b/src/remote_internal.c
> --- a/src/remote_internal.c
> +++ b/src/remote_internal.c
> @@ -95,6 +95,7 @@ struct private_data {
> struct private_data {
> int magic; /* Should be MAGIC or DEAD. */
> int sock; /* Socket. */
> + int watch; /* File handle watch */
> pid_t pid; /* PID of tunnel process */
> int uses_tls; /* TLS enabled on socket? */
> gnutls_session_t session; /* GnuTLS session (if uses_tls != 0). */
> @@ -175,7 +176,7 @@ static void make_nonnull_network (remote
> static void make_nonnull_network (remote_nonnull_network *net_dst, virNetworkPtr net_src);
> static void make_nonnull_storage_pool (remote_nonnull_storage_pool *pool_dst, virStoragePoolPtr vol_src);
> static void make_nonnull_storage_vol (remote_nonnull_storage_vol *vol_dst, virStorageVolPtr vol_src);
> -void remoteDomainEventFired(int fd, int event, void *data);
> +void remoteDomainEventFired(int watch, int fd, int event, void *data);
> static void remoteDomainProcessEvent(virConnectPtr conn, XDR *xdr);
> static void remoteDomainQueueEvent(virConnectPtr conn, XDR *xdr);
> void remoteDomainEventQueueFlush(int timer, void *opaque);
> @@ -756,12 +757,12 @@ doRemoteOpen (virConnectPtr conn,
>
> DEBUG0("Adding Handler for remote events");
> /* Set up a callback to listen on the socket data */
> - if (virEventAddHandle(priv->sock,
> - VIR_EVENT_HANDLE_READABLE |
> - VIR_EVENT_HANDLE_ERROR |
> - VIR_EVENT_HANDLE_HANGUP,
> - remoteDomainEventFired,
> - conn) < 0) {
> + if ((priv->watch = virEventAddHandle(priv->sock,
> + VIR_EVENT_HANDLE_READABLE |
> + VIR_EVENT_HANDLE_ERROR |
> + VIR_EVENT_HANDLE_HANGUP,
> + remoteDomainEventFired,
> + conn)) < 0) {
> DEBUG0("virEventAddHandle failed: No addHandleImpl defined."
> " continuing without events.");
> } else {
> @@ -5265,7 +5266,8 @@ remoteDomainQueueEvent(virConnectPtr con
> * for event data
> */
> void
> -remoteDomainEventFired(int fd ATTRIBUTE_UNUSED,
> +remoteDomainEventFired(int watch,
> + int fd,
> int event,
> void *opaque)
> {
> @@ -5278,13 +5280,18 @@ remoteDomainEventFired(int fd ATTRIBUTE_
> virConnectPtr conn = opaque;
> struct private_data *priv = conn->privateData;
>
> - DEBUG("%s : Event fired %d %X", __FUNCTION__, event, event);
> + DEBUG("Event fired %d %d %d %X", watch, fd, event, event);
>
> if (event & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR)) {
> DEBUG("%s : VIR_EVENT_HANDLE_HANGUP or "
> "VIR_EVENT_HANDLE_ERROR encountered", __FUNCTION__);
> - virEventRemoveHandle(fd);
> + virEventRemoveHandle(watch);
> return;
> + }
> +
> + if (fd != priv->sock) {
> + virEventRemoveHandle(watch);
> + return;
> }
>
> /* Read and deserialise length word. */
>
More information about the libvir-list
mailing list