[libvirt] PATCH: 3/4: Fix handling of deleted file handles

Daniel Veillard veillard at redhat.com
Tue May 12 14:52:01 UTC 2009


On Mon, May 11, 2009 at 12:21:40PM +0100, Daniel P. Berrange wrote:
> This patch fixes handling of deleted file handles. First of all it reverts
> the patch http://www.redhat.com/archives/libvir-list/2009-March/msg00246.html
> As an alternative solution to that original problem, the first thing that
> virEventRunOnce() does, is to purge all timers/watches which were marked as
> deleted. This deals with deletes that happen between invocations of the
> virEventRunOnce() method. It also ensures that when going into poll(), all
> the registered timers/watches are live. This guarentees that array indexes 
> match up between the poll FD array and our list of watches. Then during
> the dispatch of FDs, we have a simpler check to skip invocation of file
> handles / timers marked as deleted.
[...]
> -static int virEventMakePollFDs(struct pollfd **retfds) {
> +static struct pollfd *virEventMakePollFDs(void) {
>      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++) {
> -        if (eventLoop.handles[i].deleted)
> -            continue;
> -        nfds++;
> -    }
> -    *retfds = NULL;
> -    /* Setup the poll file handle data structs */
> -    if (VIR_ALLOC_N(fds, nfds) < 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("Prepare n=%d w=%d, f=%d e=%d", i,
> +                    eventLoop.handles[i].watch,
> +                    eventLoop.handles[i].fd,
> +                    eventLoop.handles[i].events);
> +        fds[i].fd = eventLoop.handles[i].fd;
> +        fds[i].events = eventLoop.handles[i].events;
> +        fds[i].revents = 0;
>          //EVENT_DEBUG("Wait for %d %d", eventLoop.handles[i].fd, eventLoop.handles[i].events);
> -        nfds++;
>      }
>  
> -    *retfds = fds;
> -    return nfds;
> +    return fds;
>  }

  Okay the loop is way simpler now

>  
> @@ -435,26 +429,30 @@ static int virEventDispatchTimeouts(void
>   * Returns 0 upon success, -1 if an error occurred
>   */
>  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) {
> -            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;
>          }
>  
> -        if (fds[n].revents) {
> +        if (fds[i].revents) {
>              virEventHandleCallback cb = eventLoop.handles[i].cb;
>              void *opaque = eventLoop.handles[i].opaque;
> -            int hEvents = virPollEventToEventHandleType(fds[n].revents);
> -            EVENT_DEBUG("Dispatch %d %d %p", fds[n].fd,
> -                        fds[n].revents, eventLoop.handles[i].opaque);
> +            int hEvents = virPollEventToEventHandleType(fds[i].revents);
> +            EVENT_DEBUG("Dispatch n=%d f=%d w=%d e=%d %p", i,
> +                        fds[i].fd, eventLoop.handles[i].watch,
> +                        fds[i].revents, eventLoop.handles[i].opaque);
>              virEventUnlock();
>              (cb)(eventLoop.handles[i].watch,
> -                 fds[n].fd, hEvents, opaque);
> +                 fds[i].fd, hEvents, opaque);
>              virEventLock();
>          }
> -        n++;
>      }
>  
>      return 0;

  and here too

> @@ -545,22 +543,21 @@ static int virEventCleanupHandles(void) 
>   * at least one file handle has an event, or a timer expires
>   */
>  int virEventRunOnce(void) {
> -    struct pollfd *fds;
> +    struct pollfd *fds = NULL;
>      int ret, timeout, nfds;
>  
>      virEventLock();
>      eventLoop.running = 1;
>      eventLoop.leader = pthread_self();
> -    if ((nfds = virEventMakePollFDs(&fds)) < 0) {
> -        virEventUnlock();
> -        return -1;
> -    }
>  
> -    if (virEventCalculateTimeout(&timeout) < 0) {
> -        VIR_FREE(fds);
> -        virEventUnlock();
> -        return -1;
> -    }
> +    if (virEventCleanupTimeouts() < 0 ||
> +        virEventCleanupHandles() < 0)
> +        goto error;
> +
> +    if (!(fds = virEventMakePollFDs()) ||
> +        virEventCalculateTimeout(&timeout) < 0)
> +        goto error;
> +    nfds = eventLoop.handlesCount;
>  
>      virEventUnlock();

  here we separate the processing

> @@ -572,38 +569,31 @@ int virEventRunOnce(void) {
>          if (errno == EINTR) {
>              goto retry;
>          }
> -        VIR_FREE(fds);
> -        return -1;
> +        goto error_unlocked;
>      }
>  
>      virEventLock();
> -    if (virEventDispatchTimeouts() < 0) {
> -        VIR_FREE(fds);
> -        virEventUnlock();
> -        return -1;
> -    }
> +    if (virEventDispatchTimeouts() < 0)
> +        goto error;
>  
>      if (ret > 0 &&
> -        virEventDispatchHandles(nfds, fds) < 0) {
> -        VIR_FREE(fds);
> -        virEventUnlock();
> -        return -1;
> -    }
> -    VIR_FREE(fds);
> +        virEventDispatchHandles(nfds, fds) < 0)
> +        goto error;
>  
> -    if (virEventCleanupTimeouts() < 0) {
> -        virEventUnlock();
> -        return -1;
> -    }
> -
> -    if (virEventCleanupHandles() < 0) {
> -        virEventUnlock();
> -        return -1;
> -    }
> +    if (virEventCleanupTimeouts() < 0 ||
> +        virEventCleanupHandles() < 0)
> +        goto error;
>  
>      eventLoop.running = 0;
>      virEventUnlock();
> +    VIR_FREE(fds);
>      return 0;
> +
> +error:
> +    virEventUnlock();
> +error_unlocked:
> +    VIR_FREE(fds);
> +    return -1;
>  }

  Okay, looks fine !

Daniel

-- 
Daniel Veillard      | libxml Gnome XML XSLT toolkit  http://xmlsoft.org/
daniel at veillard.com  | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library  http://libvirt.org/




More information about the libvir-list mailing list