Change public API for virEventAddHandle to allow multiple registrations per FD

This commit is contained in:
Daniel P. Berrange 2008-11-19 16:19:36 +00:00
parent 3d41e86534
commit 6d41cb87d3
17 changed files with 187 additions and 119 deletions

View File

@ -1,3 +1,14 @@
Wed Nov 19 16:15:00 GMT 2008 Daniel Berrange <berrange@redhat.com>
* 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 <berrange@redhat.com> Wed Nov 19 15:25:00 GMT 2008 Daniel Berrange <berrange@redhat.com>
Add a callback for freeing the user data for callbacks Add a callback for freeing the user data for callbacks

View File

@ -42,8 +42,8 @@ int myDomainEventCallback2 (virConnectPtr conn, virDomainPtr dom,
int event, int detail, void *opaque); int event, int detail, void *opaque);
int myEventAddHandleFunc (int fd, int event, int myEventAddHandleFunc (int fd, int event,
virEventHandleCallback cb, void *opaque); virEventHandleCallback cb, void *opaque);
void myEventUpdateHandleFunc(int fd, int event); void myEventUpdateHandleFunc(int watch, int event);
int myEventRemoveHandleFunc(int fd); int myEventRemoveHandleFunc(int watch);
int myEventAddTimeoutFunc(int timeout, virEventTimeoutCallback cb, int myEventAddTimeoutFunc(int timeout, virEventTimeoutCallback cb,
void *opaque); void *opaque);
@ -334,7 +334,8 @@ int main(int argc, char **argv)
} }
if(h_cb) { if(h_cb) {
h_cb(h_fd, h_cb(0,
h_fd,
myPollEventToEventHandleType(pfd.revents & h_event), myPollEventToEventHandleType(pfd.revents & h_event),
h_opaque); h_opaque);
} }

View File

@ -75,19 +75,19 @@ def myAddHandle(fd, events, cb, opaque):
mypoll.register(fd, myEventHandleTypeToPollEvent(events)) mypoll.register(fd, myEventHandleTypeToPollEvent(events))
def myUpdateHandle(fd, event): def myUpdateHandle(watch, event):
global h_fd, h_events global h_fd, h_events
#print "Updating Handle %s %s" % (str(fd), str(events)) #print "Updating Handle %s %s" % (str(fd), str(events))
h_fd = fd h_fd = fd
h_events = event h_events = event
mypoll.unregister(fd) mypoll.unregister(watch)
mypoll.register(fd, myEventHandleTypeToPollEvent(event)) mypoll.register(watch, myEventHandleTypeToPollEvent(event))
def myRemoveHandle(fd): def myRemoveHandle(watch):
global h_fd global h_fd
#print "Removing Handle %s" % str(fd) #print "Removing Handle %s" % str(fd)
h_fd = 0 h_fd = 0
mypoll.unregister(fd) mypoll.unregister(watch)
def myAddTimeout(timeout, cb, opaque): def myAddTimeout(timeout, cb, opaque):
global t_active, t_timeout, t_cb, t_opaque global t_active, t_timeout, t_cb, t_opaque
@ -175,7 +175,7 @@ def main():
if h_cb != None: if h_cb != None:
#print "Invoking Handle CB" #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]) h_opaque[0], h_opaque[1])
#print "DEBUG EXIT" #print "DEBUG EXIT"

View File

@ -1124,13 +1124,15 @@ typedef enum {
/** /**
* virEventHandleCallback: * virEventHandleCallback:
* *
* @watch: watch on which the event occurred
* @fd: file handle on which the event occurred * @fd: file handle on which the event occurred
* @events: bitset of events from virEventHandleType constants * @events: bitset of events from virEventHandleType constants
* @opaque: user data registered with handle * @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: * virEventAddHandleFunc:
@ -1140,29 +1142,33 @@ typedef void (*virEventHandleCallback)(int fd, int events, void *opaque);
* @opaque: user data to pass to the callback * @opaque: user data to pass to the callback
* *
* Part of the EventImpl, this callback Adds a file handle callback to * 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, typedef int (*virEventAddHandleFunc)(int fd, int event,
virEventHandleCallback cb, void *opaque); virEventHandleCallback cb, void *opaque);
/** /**
* virEventUpdateHandleFunc: * virEventUpdateHandleFunc:
* @fd: file descriptor to modify * @watch: file descriptor watch to modify
* @event: new events to listen on * @event: new events to listen on
* *
* Part of the EventImpl, this user-provided callback is notified when * Part of the EventImpl, this user-provided callback is notified when
* events to listen on change * events to listen on change
*/ */
typedef void (*virEventUpdateHandleFunc)(int fd, int event); typedef void (*virEventUpdateHandleFunc)(int watch, int event);
/** /**
* virEventRemoveHandleFunc: * 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 * Part of the EventImpl, this user-provided callback is notified when
* an fd is no longer being listened on * an fd is no longer being listened on
*/ */
typedef int (*virEventRemoveHandleFunc)(int fd); typedef int (*virEventRemoveHandleFunc)(int watch);
/** /**
* virEventTimeoutCallback: * virEventTimeoutCallback:

View File

@ -1124,13 +1124,15 @@ typedef enum {
/** /**
* virEventHandleCallback: * virEventHandleCallback:
* *
* @watch: watch on which the event occurred
* @fd: file handle on which the event occurred * @fd: file handle on which the event occurred
* @events: bitset of events from virEventHandleType constants * @events: bitset of events from virEventHandleType constants
* @opaque: user data registered with handle * @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: * virEventAddHandleFunc:
@ -1140,29 +1142,33 @@ typedef void (*virEventHandleCallback)(int fd, int events, void *opaque);
* @opaque: user data to pass to the callback * @opaque: user data to pass to the callback
* *
* Part of the EventImpl, this callback Adds a file handle callback to * 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, typedef int (*virEventAddHandleFunc)(int fd, int event,
virEventHandleCallback cb, void *opaque); virEventHandleCallback cb, void *opaque);
/** /**
* virEventUpdateHandleFunc: * virEventUpdateHandleFunc:
* @fd: file descriptor to modify * @watch: file descriptor watch to modify
* @event: new events to listen on * @event: new events to listen on
* *
* Part of the EventImpl, this user-provided callback is notified when * Part of the EventImpl, this user-provided callback is notified when
* events to listen on change * events to listen on change
*/ */
typedef void (*virEventUpdateHandleFunc)(int fd, int event); typedef void (*virEventUpdateHandleFunc)(int watch, int event);
/** /**
* virEventRemoveHandleFunc: * 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 * Part of the EventImpl, this user-provided callback is notified when
* an fd is no longer being listened on * an fd is no longer being listened on
*/ */
typedef int (*virEventRemoveHandleFunc)(int fd); typedef int (*virEventRemoveHandleFunc)(int watch);
/** /**
* virEventTimeoutCallback: * virEventTimeoutCallback:

View File

@ -1940,15 +1940,15 @@ static PyObject *
libvirt_virEventInvokeHandleCallback(PyObject *self ATTRIBUTE_UNUSED, libvirt_virEventInvokeHandleCallback(PyObject *self ATTRIBUTE_UNUSED,
PyObject *args) PyObject *args)
{ {
int fd, event; int watch, fd, event;
PyObject *py_f; PyObject *py_f;
PyObject *py_opaque; PyObject *py_opaque;
virEventHandleCallback cb; virEventHandleCallback cb;
void *opaque; void *opaque;
if (!PyArg_ParseTuple if (!PyArg_ParseTuple
(args, (char *) "iiOO:virEventInvokeHandleCallback", (args, (char *) "iiiOO:virEventInvokeHandleCallback",
&fd, &event, &py_f, &py_opaque &watch, &fd, &event, &py_f, &py_opaque
)) ))
return VIR_PY_INT_FAIL; return VIR_PY_INT_FAIL;
@ -1956,7 +1956,7 @@ libvirt_virEventInvokeHandleCallback(PyObject *self ATTRIBUTE_UNUSED,
opaque = (void *) PyvirVoidPtr_Get(py_opaque); opaque = (void *) PyvirVoidPtr_Get(py_opaque);
if(cb) if(cb)
cb (fd, event, opaque); cb (watch, fd, event, opaque);
return VIR_PY_INT_SUCCESS; return VIR_PY_INT_SUCCESS;
} }

View File

@ -37,6 +37,7 @@
/* State for a single file handle being monitored */ /* State for a single file handle being monitored */
struct virEventHandle { struct virEventHandle {
int watch;
int fd; int fd;
int events; int events;
virEventHandleCallback cb; virEventHandleCallback cb;
@ -71,6 +72,9 @@ struct virEventLoop {
/* Only have one event loop */ /* Only have one event loop */
static struct virEventLoop eventLoop; 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 */ /* Unique ID for the next timer to be registered */
static int nextTimer = 0; static int nextTimer = 0;
@ -91,6 +95,7 @@ int virEventAddHandleImpl(int fd, int events, virEventHandleCallback cb,
eventLoop.handlesAlloc += EVENT_ALLOC_EXTENT; eventLoop.handlesAlloc += EVENT_ALLOC_EXTENT;
} }
eventLoop.handles[eventLoop.handlesCount].watch = nextWatch++;
eventLoop.handles[eventLoop.handlesCount].fd = fd; eventLoop.handles[eventLoop.handlesCount].fd = fd;
eventLoop.handles[eventLoop.handlesCount].events = eventLoop.handles[eventLoop.handlesCount].events =
virEventHandleTypeToPollEvent(events); virEventHandleTypeToPollEvent(events);
@ -100,13 +105,13 @@ int virEventAddHandleImpl(int fd, int events, virEventHandleCallback cb,
eventLoop.handlesCount++; eventLoop.handlesCount++;
return 0; return nextWatch-1;
} }
void virEventUpdateHandleImpl(int fd, int events) { void virEventUpdateHandleImpl(int watch, int events) {
int i; int i;
for (i = 0 ; i < eventLoop.handlesCount ; i++) { for (i = 0 ; i < eventLoop.handlesCount ; i++) {
if (eventLoop.handles[i].fd == fd) { if (eventLoop.handles[i].watch == watch) {
eventLoop.handles[i].events = eventLoop.handles[i].events =
virEventHandleTypeToPollEvent(events); virEventHandleTypeToPollEvent(events);
break; break;
@ -120,15 +125,15 @@ void virEventUpdateHandleImpl(int fd, int events) {
* For this reason we only ever set a flag in the existing list. * For this reason we only ever set a flag in the existing list.
* Actual deletion will be done out-of-band * Actual deletion will be done out-of-band
*/ */
int virEventRemoveHandleImpl(int fd) { int virEventRemoveHandleImpl(int watch) {
int i; int i;
EVENT_DEBUG("Remove handle %d", fd); EVENT_DEBUG("Remove handle %d", watch);
for (i = 0 ; i < eventLoop.handlesCount ; i++) { for (i = 0 ; i < eventLoop.handlesCount ; i++) {
if (eventLoop.handles[i].deleted) if (eventLoop.handles[i].deleted)
continue; continue;
if (eventLoop.handles[i].fd == fd) { if (eventLoop.handles[i].watch == watch) {
EVENT_DEBUG("mark delete %d", i); EVENT_DEBUG("mark delete %d %d", i, eventLoop.handles[i].fd);
eventLoop.handles[i].deleted = 1; eventLoop.handles[i].deleted = 1;
return 0; return 0;
} }
@ -356,9 +361,13 @@ static int virEventDispatchHandles(struct pollfd *fds) {
if (fds[i].revents) { if (fds[i].revents) {
hEvents = virPollEventToEventHandleType(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].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); eventLoop.handles[i].opaque);
} }
} }

View File

@ -24,7 +24,7 @@
#ifndef __VIRTD_EVENT_H__ #ifndef __VIRTD_EVENT_H__
#define __VIRTD_EVENT_H__ #define __VIRTD_EVENT_H__
#include "../src/event.h" #include "internal.h"
/** /**
* virEventAddHandleImpl: register a callback for monitoring file handle events * 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 * 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 * @events: bitset of events to watch from POLLnnn constants
* *
* Will not fail if fd exists * 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 * 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 * 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 * virEventAddTimeoutImpl: register a callback for a timer event

View File

@ -68,6 +68,7 @@ struct libvirtd_mdns {
/* Avahi API requires this struct names in the app :-( */ /* Avahi API requires this struct names in the app :-( */
struct AvahiWatch { struct AvahiWatch {
int watch;
int fd; int fd;
int revents; int revents;
AvahiWatchCallback callback; 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; AvahiWatch *w = (AvahiWatch*)opaque;
int fd_events = virEventHandleTypeToPollEvent(events); 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->revents = fd_events;
w->callback(w, fd, fd_events, w->userdata); w->callback(w, fd, fd_events, w->userdata);
} }
static AvahiWatch *libvirtd_mdns_watch_new(const AvahiPoll *api ATTRIBUTE_UNUSED, 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; AvahiWatch *w;
virEventHandleType hEvents; virEventHandleType hEvents;
if (VIR_ALLOC(w) < 0) 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); AVAHI_DEBUG("New handle %p FD %d Event %d", w, w->fd, event);
hEvents = virPollEventToEventHandleType(event); hEvents = virPollEventToEventHandleType(event);
if (virEventAddHandleImpl(fd, hEvents, if ((w->watch = virEventAddHandleImpl(fd, hEvents,
libvirtd_mdns_watch_dispatch, w) < 0) { libvirtd_mdns_watch_dispatch, w)) < 0) {
VIR_FREE(w); VIR_FREE(w);
return NULL; 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) static void libvirtd_mdns_watch_update(AvahiWatch *w, AvahiWatchEvent event)
{ {
AVAHI_DEBUG("Update handle %p FD %d Event %d", w, w->fd, 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) 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) static void libvirtd_mdns_watch_free(AvahiWatch *w)
{ {
AVAHI_DEBUG("Free handle %p %d", w, w->fd); AVAHI_DEBUG("Free handle %p %d", w, w->fd);
virEventRemoveHandleImpl(w->fd); virEventRemoveHandleImpl(w->watch);
VIR_FREE(w); VIR_FREE(w);
} }

View File

@ -142,8 +142,8 @@ static void sig_handler(int sig, siginfo_t * siginfo,
errno = origerrno; errno = origerrno;
} }
static void qemudDispatchClientEvent(int fd, int events, void *opaque); static void qemudDispatchClientEvent(int watch, int fd, int events, void *opaque);
static void qemudDispatchServerEvent(int fd, int events, void *opaque); static void qemudDispatchServerEvent(int watch, int fd, int events, void *opaque);
static int qemudRegisterClientEvent(struct qemud_server *server, static int qemudRegisterClientEvent(struct qemud_server *server,
struct qemud_client *client, struct qemud_client *client,
int removeFirst); int removeFirst);
@ -245,7 +245,8 @@ remoteInitializeGnuTLS (void)
} }
static void static void
qemudDispatchSignalEvent(int fd ATTRIBUTE_UNUSED, qemudDispatchSignalEvent(int watch ATTRIBUTE_UNUSED,
int fd ATTRIBUTE_UNUSED,
int events ATTRIBUTE_UNUSED, int events ATTRIBUTE_UNUSED,
void *opaque) { void *opaque) {
struct qemud_server *server = (struct qemud_server *)opaque; struct qemud_server *server = (struct qemud_server *)opaque;
@ -534,12 +535,12 @@ static int qemudListenUnix(struct qemud_server *server,
goto cleanup; goto cleanup;
} }
if (virEventAddHandleImpl(sock->fd, if ((sock->watch = virEventAddHandleImpl(sock->fd,
VIR_EVENT_HANDLE_READABLE | VIR_EVENT_HANDLE_READABLE |
VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_ERROR |
VIR_EVENT_HANDLE_HANGUP, VIR_EVENT_HANDLE_HANGUP,
qemudDispatchServerEvent, qemudDispatchServerEvent,
server) < 0) { server)) < 0) {
qemudLog(QEMUD_ERR, "%s", qemudLog(QEMUD_ERR, "%s",
_("Failed to add server event callback")); _("Failed to add server event callback"));
goto cleanup; goto cleanup;
@ -666,12 +667,12 @@ remoteListenTCP (struct qemud_server *server,
goto cleanup; goto cleanup;
} }
if (virEventAddHandleImpl(sock->fd, if ((sock->watch = virEventAddHandleImpl(sock->fd,
VIR_EVENT_HANDLE_READABLE | VIR_EVENT_HANDLE_READABLE |
VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_ERROR |
VIR_EVENT_HANDLE_HANGUP, VIR_EVENT_HANDLE_HANGUP,
qemudDispatchServerEvent, qemudDispatchServerEvent,
server) < 0) { server)) < 0) {
qemudLog(QEMUD_ERR, "%s", _("Failed to add server event callback")); qemudLog(QEMUD_ERR, "%s", _("Failed to add server event callback"));
goto cleanup; goto cleanup;
} }
@ -1232,7 +1233,7 @@ static void qemudDispatchClientFailure(struct qemud_server *server, struct qemud
tmp = tmp->next; tmp = tmp->next;
} }
virEventRemoveHandleImpl(client->fd); virEventRemoveHandleImpl(client->watch);
/* Deregister event delivery callback */ /* Deregister event delivery callback */
if(client->conn) { if(client->conn) {
@ -1596,12 +1597,12 @@ qemudDispatchClientWrite(struct qemud_server *server,
static void 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_server *server = (struct qemud_server *)opaque;
struct qemud_client *client = server->clients; struct qemud_client *client = server->clients;
while (client) { while (client) {
if (client->fd == fd) if (client->watch == watch)
break; break;
client = client->next; client = client->next;
@ -1610,6 +1611,9 @@ qemudDispatchClientEvent(int fd, int events, void *opaque) {
if (!client) if (!client)
return; return;
if (client->fd != fd)
return;
if (events == VIR_EVENT_HANDLE_WRITABLE) if (events == VIR_EVENT_HANDLE_WRITABLE)
qemudDispatchClientWrite(server, client); qemudDispatchClientWrite(server, client);
else if (events == VIR_EVENT_HANDLE_READABLE) else if (events == VIR_EVENT_HANDLE_READABLE)
@ -1644,26 +1648,26 @@ static int qemudRegisterClientEvent(struct qemud_server *server,
} }
if (removeFirst) if (removeFirst)
if (virEventRemoveHandleImpl(client->fd) < 0) if (virEventRemoveHandleImpl(client->watch) < 0)
return -1; return -1;
if (virEventAddHandleImpl(client->fd, if ((client->watch = virEventAddHandleImpl(client->fd,
mode | VIR_EVENT_HANDLE_ERROR | mode | VIR_EVENT_HANDLE_ERROR |
VIR_EVENT_HANDLE_HANGUP, VIR_EVENT_HANDLE_HANGUP,
qemudDispatchClientEvent, qemudDispatchClientEvent,
server) < 0) server)) < 0)
return -1; return -1;
return 0; return 0;
} }
static void 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_server *server = (struct qemud_server *)opaque;
struct qemud_socket *sock = server->sockets; struct qemud_socket *sock = server->sockets;
while (sock) { while (sock) {
if (sock->fd == fd) if (sock->watch == watch)
break; break;
sock = sock->next; sock = sock->next;
@ -1672,6 +1676,9 @@ qemudDispatchServerEvent(int fd, int events, void *opaque) {
if (!sock) if (!sock)
return; return;
if (sock->fd != fd)
return;
if (events) if (events)
qemudDispatchServer(server, sock); qemudDispatchServer(server, sock);
} }

View File

@ -96,6 +96,7 @@ struct qemud_client {
int magic; int magic;
int fd; int fd;
int watch;
int readonly; int readonly;
enum qemud_mode mode; enum qemud_mode mode;
@ -141,6 +142,7 @@ struct qemud_client {
struct qemud_socket { struct qemud_socket {
int fd; int fd;
int watch;
int readonly; int readonly;
int type; /* qemud_sock_type */ int type; /* qemud_sock_type */
int auth; int auth;

View File

@ -455,8 +455,11 @@ typedef virDomainObj *virDomainObjPtr;
struct _virDomainObj { struct _virDomainObj {
int stdin_fd; int stdin_fd;
int stdout_fd; int stdout_fd;
int stdout_watch;
int stderr_fd; int stderr_fd;
int stderr_watch;
int monitor; int monitor;
int monitorWatch;
int logfile; int logfile;
int pid; int pid;
int state; int state;

View File

@ -42,15 +42,15 @@ int virEventAddHandle(int fd, int events, virEventHandleCallback cb,
return addHandleImpl(fd, events, cb, opaque); return addHandleImpl(fd, events, cb, opaque);
} }
void virEventUpdateHandle(int fd, int events) { void virEventUpdateHandle(int watch, int events) {
updateHandleImpl(fd, events); updateHandleImpl(watch, events);
} }
int virEventRemoveHandle(int fd) { int virEventRemoveHandle(int watch) {
if (!removeHandleImpl) if (!removeHandleImpl)
return -1; return -1;
return removeHandleImpl(fd); return removeHandleImpl(watch);
} }
int virEventAddTimeout(int timeout, virEventTimeoutCallback cb, void *opaque) { int virEventAddTimeout(int timeout, virEventTimeoutCallback cb, void *opaque) {

View File

@ -40,21 +40,21 @@ int virEventAddHandle(int fd, int events, virEventHandleCallback cb,
/** /**
* virEventUpdateHandle: change event set for a monitored file handle * 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 * @events: bitset of events to watch from virEventHandleType constants
* *
* Will not fail if fd exists * 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 * 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 * 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 * virEventAddTimeout: register a callback for a timer event

View File

@ -387,7 +387,7 @@ static int lxcVMCleanup(virConnectPtr conn,
DEBUG("container exited with rc: %d", rc); DEBUG("container exited with rc: %d", rc);
} }
virEventRemoveHandle(vm->monitor); virEventRemoveHandle(vm->monitorWatch);
close(vm->monitor); close(vm->monitor);
virFileDeletePid(driver->stateDir, vm->def->name); virFileDeletePid(driver->stateDir, vm->def->name);
@ -582,7 +582,8 @@ static int lxcVmTerminate(virConnectPtr conn,
return lxcVMCleanup(conn, driver, vm); return lxcVMCleanup(conn, driver, vm);
} }
static void lxcMonitorEvent(int fd, static void lxcMonitorEvent(int watch,
int fd,
int events ATTRIBUTE_UNUSED, int events ATTRIBUTE_UNUSED,
void *data) void *data)
{ {
@ -591,18 +592,23 @@ static void lxcMonitorEvent(int fd,
unsigned int i; unsigned int i;
for (i = 0 ; i < driver->domains.count ; 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]; vm = driver->domains.objs[i];
break; break;
} }
} }
if (!vm) { if (!vm) {
virEventRemoveHandle(fd); virEventRemoveHandle(watch);
return;
}
if (vm->monitor != fd) {
virEventRemoveHandle(watch);
return; return;
} }
if (lxcVmTerminate(NULL, driver, vm, SIGINT) < 0) 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->def->id = vm->pid;
vm->state = VIR_DOMAIN_RUNNING; vm->state = VIR_DOMAIN_RUNNING;
if (virEventAddHandle(vm->monitor, if ((vm->monitorWatch = virEventAddHandle(
vm->monitor,
VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_HANGUP, VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_HANGUP,
lxcMonitorEvent, lxcMonitorEvent,
driver) < 0) { driver)) < 0) {
lxcVmTerminate(conn, driver, vm, 0); lxcVmTerminate(conn, driver, vm, 0);
goto cleanup; goto cleanup;
} }

View File

@ -110,7 +110,8 @@ static void qemudDomainEventDispatch (struct qemud_driver *driver,
int event, int event,
int detail); int detail);
static void qemudDispatchVMEvent(int fd, static void qemudDispatchVMEvent(int watch,
int fd,
int events, int events,
void *opaque); void *opaque);
@ -946,18 +947,18 @@ static int qemudStartVMDaemon(virConnectPtr conn,
} }
if (ret == 0) { if (ret == 0) {
if ((virEventAddHandle(vm->stdout_fd, if (((vm->stdout_watch = virEventAddHandle(vm->stdout_fd,
VIR_EVENT_HANDLE_READABLE | VIR_EVENT_HANDLE_READABLE |
VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_ERROR |
VIR_EVENT_HANDLE_HANGUP, VIR_EVENT_HANDLE_HANGUP,
qemudDispatchVMEvent, qemudDispatchVMEvent,
driver) < 0) || driver)) < 0) ||
(virEventAddHandle(vm->stderr_fd, ((vm->stderr_watch = virEventAddHandle(vm->stderr_fd,
VIR_EVENT_HANDLE_READABLE | VIR_EVENT_HANDLE_READABLE |
VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_ERROR |
VIR_EVENT_HANDLE_HANGUP, VIR_EVENT_HANDLE_HANGUP,
qemudDispatchVMEvent, qemudDispatchVMEvent,
driver) < 0) || driver)) < 0) ||
(qemudWaitForMonitor(conn, driver, vm) < 0) || (qemudWaitForMonitor(conn, driver, vm) < 0) ||
(qemudDetectVcpuPIDs(conn, driver, vm) < 0) || (qemudDetectVcpuPIDs(conn, driver, vm) < 0) ||
(qemudInitCpus(conn, driver, vm, migrateFrom) < 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->stdout_fd);
qemudVMData(driver, vm, vm->stderr_fd); qemudVMData(driver, vm, vm->stderr_fd);
virEventRemoveHandle(vm->stdout_fd); virEventRemoveHandle(vm->stdout_watch);
virEventRemoveHandle(vm->stderr_fd); virEventRemoveHandle(vm->stderr_watch);
if (close(vm->logfile) < 0) if (close(vm->logfile) < 0)
qemudLog(QEMUD_WARN, _("Unable to close logfile %d: %s\n"), 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 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; struct qemud_driver *driver = (struct qemud_driver *)opaque;
virDomainObjPtr vm = NULL; virDomainObjPtr vm = NULL;
unsigned int i; unsigned int i;
for (i = 0 ; i < driver->domains.count ; i++) { for (i = 0 ; i < driver->domains.count ; i++) {
if (virDomainIsActive(driver->domains.objs[i]) && if (virDomainIsActive(driver->domains.objs[i]) &&
(driver->domains.objs[i]->stdout_fd == fd || (driver->domains.objs[i]->stdout_watch == watch ||
driver->domains.objs[i]->stderr_fd == fd)) { driver->domains.objs[i]->stderr_watch == watch)) {
vm = driver->domains.objs[i]; vm = driver->domains.objs[i];
break; break;
} }
@ -1089,6 +1090,12 @@ qemudDispatchVMEvent(int fd, int events, void *opaque) {
if (!vm) if (!vm)
return; return;
if (vm->stdout_fd != fd &&
vm->stderr_fd != fd) {
qemudDispatchVMFailure(driver, vm, fd);
return;
}
if (events == VIR_EVENT_HANDLE_READABLE) if (events == VIR_EVENT_HANDLE_READABLE)
qemudDispatchVMLog(driver, vm, fd); qemudDispatchVMLog(driver, vm, fd);
else else

View File

@ -95,6 +95,7 @@ static int inside_daemon = 0;
struct private_data { struct private_data {
int magic; /* Should be MAGIC or DEAD. */ int magic; /* Should be MAGIC or DEAD. */
int sock; /* Socket. */ int sock; /* Socket. */
int watch; /* File handle watch */
pid_t pid; /* PID of tunnel process */ pid_t pid; /* PID of tunnel process */
int uses_tls; /* TLS enabled on socket? */ int uses_tls; /* TLS enabled on socket? */
gnutls_session_t session; /* GnuTLS session (if uses_tls != 0). */ 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_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_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); 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 remoteDomainProcessEvent(virConnectPtr conn, XDR *xdr);
static void remoteDomainQueueEvent(virConnectPtr conn, XDR *xdr); static void remoteDomainQueueEvent(virConnectPtr conn, XDR *xdr);
void remoteDomainEventQueueFlush(int timer, void *opaque); void remoteDomainEventQueueFlush(int timer, void *opaque);
@ -756,12 +757,12 @@ doRemoteOpen (virConnectPtr conn,
DEBUG0("Adding Handler for remote events"); DEBUG0("Adding Handler for remote events");
/* Set up a callback to listen on the socket data */ /* Set up a callback to listen on the socket data */
if (virEventAddHandle(priv->sock, if ((priv->watch = virEventAddHandle(priv->sock,
VIR_EVENT_HANDLE_READABLE | VIR_EVENT_HANDLE_READABLE |
VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_ERROR |
VIR_EVENT_HANDLE_HANGUP, VIR_EVENT_HANDLE_HANGUP,
remoteDomainEventFired, remoteDomainEventFired,
conn) < 0) { conn)) < 0) {
DEBUG0("virEventAddHandle failed: No addHandleImpl defined." DEBUG0("virEventAddHandle failed: No addHandleImpl defined."
" continuing without events."); " continuing without events.");
} else { } else {
@ -5266,7 +5267,8 @@ remoteDomainQueueEvent(virConnectPtr conn, XDR *xdr)
* for event data * for event data
*/ */
void void
remoteDomainEventFired(int fd ATTRIBUTE_UNUSED, remoteDomainEventFired(int watch,
int fd,
int event, int event,
void *opaque) void *opaque)
{ {
@ -5279,12 +5281,17 @@ remoteDomainEventFired(int fd ATTRIBUTE_UNUSED,
virConnectPtr conn = opaque; virConnectPtr conn = opaque;
struct private_data *priv = conn->privateData; 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)) { if (event & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR)) {
DEBUG("%s : VIR_EVENT_HANDLE_HANGUP or " DEBUG("%s : VIR_EVENT_HANDLE_HANGUP or "
"VIR_EVENT_HANDLE_ERROR encountered", __FUNCTION__); "VIR_EVENT_HANDLE_ERROR encountered", __FUNCTION__);
virEventRemoveHandle(fd); virEventRemoveHandle(watch);
return;
}
if (fd != priv->sock) {
virEventRemoveHandle(watch);
return; return;
} }