Fix watch/timer event deletion

This commit is contained in:
Daniel P. Berrange 2009-05-12 16:43:04 +00:00
parent 0a31be6ba2
commit 470317f5c7
2 changed files with 59 additions and 62 deletions

View File

@ -1,3 +1,10 @@
Tue May 12 17:43:22 BST 2009 Daniel P. Berrange <berrange@redhat.com>
Fix watch/timer event deletion
* qemud/event.c: Change handling of deleted watches/timers
to ensure correct dispatch of callbacks when deleted flag
is set
Tue May 12 17:42:22 BST 2009 Daniel P. Berrange <berrange@redhat.com> Tue May 12 17:42:22 BST 2009 Daniel P. Berrange <berrange@redhat.com>
* qemud/event.c: Start watch/timer IDs from 1 to avoid problem * qemud/event.c: Start watch/timer IDs from 1 to avoid problem

View File

@ -313,7 +313,7 @@ static int virEventCalculateTimeout(int *timeout) {
EVENT_DEBUG("Calculate expiry of %d timers", eventLoop.timeoutsCount); EVENT_DEBUG("Calculate expiry of %d timers", eventLoop.timeoutsCount);
/* Figure out if we need a timeout */ /* Figure out if we need a timeout */
for (i = 0 ; i < eventLoop.timeoutsCount ; i++) { for (i = 0 ; i < eventLoop.timeoutsCount ; i++) {
if (eventLoop.timeouts[i].deleted || eventLoop.timeouts[i].frequency < 0) if (eventLoop.timeouts[i].frequency < 0)
continue; continue;
EVENT_DEBUG("Got a timeout scheduled for %llu", eventLoop.timeouts[i].expiresAt); EVENT_DEBUG("Got a timeout scheduled for %llu", eventLoop.timeouts[i].expiresAt);
@ -350,32 +350,26 @@ static int virEventCalculateTimeout(int *timeout) {
* file handles. The caller must free the returned data struct * file handles. The caller must free the returned data struct
* returns: the pollfd array, or NULL on error * returns: the pollfd array, or NULL on error
*/ */
static int virEventMakePollFDs(struct pollfd **retfds) { static struct pollfd *virEventMakePollFDs(void) {
struct pollfd *fds; struct pollfd *fds;
int i, nfds = 0; int i;
/* Setup the poll file handle data structs */
if (VIR_ALLOC_N(fds, eventLoop.handlesCount) < 0)
return NULL;
for (i = 0 ; i < eventLoop.handlesCount ; i++) { for (i = 0 ; i < eventLoop.handlesCount ; i++) {
if (eventLoop.handles[i].deleted) EVENT_DEBUG("Prepare n=%d w=%d, f=%d e=%d", i,
continue; eventLoop.handles[i].watch,
nfds++; eventLoop.handles[i].fd,
} eventLoop.handles[i].events);
*retfds = NULL; fds[i].fd = eventLoop.handles[i].fd;
/* Setup the poll file handle data structs */ fds[i].events = eventLoop.handles[i].events;
if (VIR_ALLOC_N(fds, nfds) < 0) fds[i].revents = 0;
return -1;
for (i = 0, nfds = 0 ; i < eventLoop.handlesCount ; i++) {
if (eventLoop.handles[i].deleted)
continue;
fds[nfds].fd = eventLoop.handles[i].fd;
fds[nfds].events = eventLoop.handles[i].events;
fds[nfds].revents = 0;
//EVENT_DEBUG("Wait for %d %d", eventLoop.handles[i].fd, eventLoop.handles[i].events); //EVENT_DEBUG("Wait for %d %d", eventLoop.handles[i].fd, eventLoop.handles[i].events);
nfds++;
} }
*retfds = fds; return fds;
return nfds;
} }
@ -435,26 +429,30 @@ static int virEventDispatchTimeouts(void) {
* Returns 0 upon success, -1 if an error occurred * Returns 0 upon success, -1 if an error occurred
*/ */
static int virEventDispatchHandles(int nfds, struct pollfd *fds) { static int virEventDispatchHandles(int nfds, struct pollfd *fds) {
int i, n; int i;
for (i = 0, n = 0 ; i < eventLoop.handlesCount && n < nfds ; i++) { /* NB, use nfds not eventLoop.handlesCount, because new
* fds might be added on end of list, and they're not
* in the fds array we've got */
for (i = 0 ; i < nfds ; i++) {
if (eventLoop.handles[i].deleted) { if (eventLoop.handles[i].deleted) {
EVENT_DEBUG("Skip deleted %d", eventLoop.handles[i].fd); EVENT_DEBUG("Skip deleted n=%d w=%d f=%d", i,
eventLoop.handles[i].watch, eventLoop.handles[i].fd);
continue; continue;
} }
if (fds[n].revents) { if (fds[i].revents) {
virEventHandleCallback cb = eventLoop.handles[i].cb; virEventHandleCallback cb = eventLoop.handles[i].cb;
void *opaque = eventLoop.handles[i].opaque; void *opaque = eventLoop.handles[i].opaque;
int hEvents = virPollEventToEventHandleType(fds[n].revents); int hEvents = virPollEventToEventHandleType(fds[i].revents);
EVENT_DEBUG("Dispatch %d %d %p", fds[n].fd, EVENT_DEBUG("Dispatch n=%d f=%d w=%d e=%d %p", i,
fds[n].revents, eventLoop.handles[i].opaque); fds[i].fd, eventLoop.handles[i].watch,
fds[i].revents, eventLoop.handles[i].opaque);
virEventUnlock(); virEventUnlock();
(cb)(eventLoop.handles[i].watch, (cb)(eventLoop.handles[i].watch,
fds[n].fd, hEvents, opaque); fds[i].fd, hEvents, opaque);
virEventLock(); virEventLock();
} }
n++;
} }
return 0; return 0;
@ -545,22 +543,21 @@ static int virEventCleanupHandles(void) {
* at least one file handle has an event, or a timer expires * at least one file handle has an event, or a timer expires
*/ */
int virEventRunOnce(void) { int virEventRunOnce(void) {
struct pollfd *fds; struct pollfd *fds = NULL;
int ret, timeout, nfds; int ret, timeout, nfds;
virEventLock(); virEventLock();
eventLoop.running = 1; eventLoop.running = 1;
eventLoop.leader = pthread_self(); eventLoop.leader = pthread_self();
if ((nfds = virEventMakePollFDs(&fds)) < 0) {
virEventUnlock();
return -1;
}
if (virEventCalculateTimeout(&timeout) < 0) { if (virEventCleanupTimeouts() < 0 ||
VIR_FREE(fds); virEventCleanupHandles() < 0)
virEventUnlock(); goto error;
return -1;
} if (!(fds = virEventMakePollFDs()) ||
virEventCalculateTimeout(&timeout) < 0)
goto error;
nfds = eventLoop.handlesCount;
virEventUnlock(); virEventUnlock();
@ -572,38 +569,31 @@ int virEventRunOnce(void) {
if (errno == EINTR) { if (errno == EINTR) {
goto retry; goto retry;
} }
VIR_FREE(fds); goto error_unlocked;
return -1;
} }
virEventLock(); virEventLock();
if (virEventDispatchTimeouts() < 0) { if (virEventDispatchTimeouts() < 0)
VIR_FREE(fds); goto error;
virEventUnlock();
return -1;
}
if (ret > 0 && if (ret > 0 &&
virEventDispatchHandles(nfds, fds) < 0) { virEventDispatchHandles(nfds, fds) < 0)
VIR_FREE(fds); goto error;
virEventUnlock();
return -1;
}
VIR_FREE(fds);
if (virEventCleanupTimeouts() < 0) { if (virEventCleanupTimeouts() < 0 ||
virEventUnlock(); virEventCleanupHandles() < 0)
return -1; goto error;
}
if (virEventCleanupHandles() < 0) {
virEventUnlock();
return -1;
}
eventLoop.running = 0; eventLoop.running = 0;
virEventUnlock(); virEventUnlock();
VIR_FREE(fds);
return 0; return 0;
error:
virEventUnlock();
error_unlocked:
VIR_FREE(fds);
return -1;
} }
static void virEventHandleWakeup(int watch ATTRIBUTE_UNUSED, static void virEventHandleWakeup(int watch ATTRIBUTE_UNUSED,