[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