]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
event: fix event-handling data race
authorEric Blake <eblake@redhat.com>
Fri, 21 Jan 2011 19:57:03 +0000 (12:57 -0700)
committerEric Blake <eblake@redhat.com>
Fri, 21 Jan 2011 22:54:54 +0000 (15:54 -0700)
This bug has been present since before the time that commit
f8a519 (Dec 2008) tried to make the dispatch loop re-entrant.

Dereferencing eventLoop.handles outside the lock risks crashing, since
any other thread could have reallocated the array in the meantime.
It's a narrow race window, however, and one that would have most
likely resulted in passing bogus data to the callback rather than
actually causing a segv, which is probably why it has gone undetected
this long.

* daemon/event.c (virEventDispatchHandles): Cache data while
inside the lock, as the array might be reallocated once outside.

daemon/event.c

index 89ca9f081324d6ede306d6ff2fb1aec642167061..4198b37198d353ba1b8c3e0bdaf2764c314a70d1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * event.c: event loop for monitoring file handles
  *
- * Copyright (C) 2007, 2010 Red Hat, Inc.
+ * Copyright (C) 2007, 2010-2011 Red Hat, Inc.
  * Copyright (C) 2007 Daniel P. Berrange
  *
  * This library is free software; you can redistribute it and/or
@@ -458,14 +458,13 @@ static int virEventDispatchHandles(int nfds, struct pollfd *fds) {
 
         if (fds[n].revents) {
             virEventHandleCallback cb = eventLoop.handles[i].cb;
+            int watch = eventLoop.handles[i].watch;
             void *opaque = eventLoop.handles[i].opaque;
             int hEvents = virPollEventToEventHandleType(fds[n].revents);
             EVENT_DEBUG("Dispatch n=%d f=%d w=%d e=%d %p", i,
-                        fds[n].fd, eventLoop.handles[i].watch,
-                        fds[n].revents, eventLoop.handles[i].opaque);
+                        fds[n].fd, watch, fds[n].revents, opaque);
             virMutexUnlock(&eventLoop.lock);
-            (cb)(eventLoop.handles[i].watch,
-                 fds[n].fd, hEvents, opaque);
+            (cb)(watch, fds[n].fd, hEvents, opaque);
             virMutexLock(&eventLoop.lock);
         }
     }