From 6d41cb87d326c96fbf6e01446508f3c408c5b018 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Wed, 19 Nov 2008 16:19:36 +0000 Subject: [PATCH] Change public API for virEventAddHandle to allow multiple registrations per FD --- ChangeLog | 11 ++++ examples/domain-events/events-c/event-test.c | 7 ++- .../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 +++++---- 17 files changed, 187 insertions(+), 119 deletions(-) diff --git a/ChangeLog b/ChangeLog index c8cff8cdc0..c589c38fcb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +Wed Nov 19 16:15:00 GMT 2008 Daniel Berrange + + * include/libvirt/libvirt.h.in: Change semantics of AddHandle + to allow for same FD to be registered more than once with + varying flags. + * qemud/event.c, qemud/event.h, qemud/mdns.c, qemud/qemud.c, + qemud/qemud.h, src/domain_conf.h, src/event.c, src/event.h, + src/lxc_driver.c, src/qemu_driver.c, src/remote_internal.c: + Update to track file handle events via the watch number + as per new public API contract + Wed Nov 19 15:25:00 GMT 2008 Daniel Berrange Add a callback for freeing the user data for callbacks diff --git a/examples/domain-events/events-c/event-test.c b/examples/domain-events/events-c/event-test.c index 11d62c7cdc..df463cf2cd 100644 --- a/examples/domain-events/events-c/event-test.c +++ b/examples/domain-events/events-c/event-test.c @@ -42,8 +42,8 @@ int myDomainEventCallback2 (virConnectPtr conn, virDomainPtr dom, 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); @@ -334,7 +334,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 index d78ff60b05..45aaa93d87 100644 --- 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 index c1970ab6d9..af2ee2cfd5 100644 --- a/include/libvirt/libvirt.h +++ b/include/libvirt/libvirt.h @@ -1124,13 +1124,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: @@ -1140,29 +1142,33 @@ typedef void (*virEventHandleCallback)(int fd, int events, void *opaque); * @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 index d3e351d2aa..08712d03b7 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -1124,13 +1124,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: @@ -1140,29 +1142,33 @@ typedef void (*virEventHandleCallback)(int fd, int events, void *opaque); * @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 index 3888af5b4e..8fb9d60d93 100644 --- a/python/libvir.c +++ b/python/libvir.c @@ -1940,15 +1940,15 @@ static PyObject * 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(PyObject *self ATTRIBUTE_UNUSED, 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 index 9b4dee71bf..3054064a94 100644 --- 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 events, virEventHandleCallback cb, 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 events, virEventHandleCallback cb, 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, int events) { * 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(struct pollfd *fds) { 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 index c359089b55..3bad232380 100644 --- 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 events, virEventHandleCallback cb, /** * 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 index 06eb9f0d24..2e74808971 100644 --- 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_callback(AvahiClient *c, AvahiClientState state } -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_new(const AvahiPoll *api ATTRIBUTE_UNUSED 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 AvahiWatch *libvirtd_mdns_watch_new(const AvahiPoll *api ATTRIBUTE_UNUSED 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 AvahiWatchEvent libvirtd_mdns_watch_get_events(AvahiWatch *w) 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 index a247dce792..c3ef35cdbc 100644 --- a/qemud/qemud.c +++ b/qemud/qemud.c @@ -142,8 +142,8 @@ static void sig_handler(int sig, siginfo_t * 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_server *server, 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 *server, 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(struct qemud_server *server, struct qemud tmp = tmp->next; } - virEventRemoveHandleImpl(client->fd); + virEventRemoveHandleImpl(client->watch); /* Deregister event delivery callback */ if(client->conn) { @@ -1596,12 +1597,12 @@ qemudDispatchClientWrite(struct qemud_server *server, 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; @@ -1610,6 +1611,9 @@ qemudDispatchClientEvent(int fd, int events, void *opaque) { if (!client) return; + if (client->fd != fd) + return; + if (events == VIR_EVENT_HANDLE_WRITABLE) qemudDispatchClientWrite(server, client); else if (events == VIR_EVENT_HANDLE_READABLE) @@ -1644,26 +1648,26 @@ static int qemudRegisterClientEvent(struct qemud_server *server, } 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; @@ -1672,6 +1676,9 @@ qemudDispatchServerEvent(int fd, int events, void *opaque) { if (!sock) return; + if (sock->fd != fd) + return; + if (events) qemudDispatchServer(server, sock); } diff --git a/qemud/qemud.h b/qemud/qemud.h index 700d2ee046..ef5379184c 100644 --- 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 index 448723f622..88fd6d5da9 100644 --- a/src/domain_conf.h +++ b/src/domain_conf.h @@ -455,8 +455,11 @@ typedef virDomainObj *virDomainObjPtr; 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 index ac6f886264..b0ee8b669d 100644 --- a/src/event.c +++ b/src/event.c @@ -42,15 +42,15 @@ int virEventAddHandle(int fd, int events, virEventHandleCallback cb, 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 index f540384259..fc804c2a79 100644 --- a/src/event.h +++ b/src/event.h @@ -40,21 +40,21 @@ int virEventAddHandle(int fd, int events, virEventHandleCallback cb, /** * 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 index e8aa018b7c..ec206b715c 100644 --- a/src/lxc_driver.c +++ b/src/lxc_driver.c @@ -387,7 +387,7 @@ static int lxcVMCleanup(virConnectPtr conn, 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 conn, 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 index 641690e6be..d43119040b 100644 --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -110,7 +110,8 @@ static void qemudDomainEventDispatch (struct qemud_driver *driver, 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(virConnectPtr conn, } 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(virConnectPtr conn ATTRIBUTE_UNUSED, 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 qemud_driver *driver, virDomainObjPtr v 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; } @@ -1089,6 +1090,12 @@ qemudDispatchVMEvent(int fd, int events, void *opaque) { 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); else diff --git a/src/remote_internal.c b/src/remote_internal.c index 63e7c4a426..08f6aeca0e 100644 --- a/src/remote_internal.c +++ b/src/remote_internal.c @@ -95,6 +95,7 @@ static int inside_daemon = 0; 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_domain (remote_nonnull_domain *dom_dst, virDomainPtr do 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 { @@ -5266,7 +5267,8 @@ remoteDomainQueueEvent(virConnectPtr conn, XDR *xdr) * for event data */ void -remoteDomainEventFired(int fd ATTRIBUTE_UNUSED, +remoteDomainEventFired(int watch, + int fd, int event, void *opaque) { @@ -5279,15 +5281,20 @@ remoteDomainEventFired(int fd ATTRIBUTE_UNUSED, 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. */ if (really_read (conn, priv, 0, buffer2, sizeof buffer2) == -1) return;