[libvirt] PATCH: Change signature of virEventAddHandle to allow multiple calls per FD

Daniel P. Berrange berrange at redhat.com
Mon Nov 17 16:58:51 UTC 2008


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. */

-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|




More information about the libvir-list mailing list