Fixed a major CPU leak when using select hub. When adding a descriptor to the hub, entries were made in all three dictionaries, readers, writers, and exc, even if the callback is None. Thus every fd would be passed into all three lists when calling select regardless of whether there was a callback for that event or not. When reading the next request out of a keepalive socket, the socket would come back as ready for writing, the hub would notice the callback is None and ignore it, and then loop as fast as possible consuming CPU.

This commit is contained in:
donovan
2008-07-17 15:30:39 -07:00
parent 09c5a8e166
commit 283270075a
2 changed files with 17 additions and 4 deletions

2
NEWS
View File

@@ -4,6 +4,8 @@ Fix a major memory leak when using the libevent or libev hubs. Timers were not b
It's now possible to use eventlet's SSL client to talk to eventlet's SSL server. (Thanks to Ryan Williams) It's now possible to use eventlet's SSL client to talk to eventlet's SSL server. (Thanks to Ryan Williams)
Fixed a major CPU leak when using select hub. When adding a descriptor to the hub, entries were made in all three dictionaries, readers, writers, and exc, even if the callback is None. Thus every fd would be passed into all three lists when calling select regardless of whether there was a callback for that event or not. When reading the next request out of a keepalive socket, the socket would come back as ready for writing, the hub would notice the callback is None and ignore it, and then loop as fast as possible consuming CPU.
0.6.x 0.6.x
===== =====

View File

@@ -78,10 +78,21 @@ class BaseHub(object):
so the exc callback happens instead of the respective read or write so the exc callback happens instead of the respective read or write
callback. callback.
""" """
read = read or self.readers.get(fileno)
self.readers[fileno] = read or self.readers.get(fileno) if read is not None:
self.writers[fileno] = write or self.writers.get(fileno) self.readers[fileno] = read
self.excs[fileno] = exc or self.excs.get(fileno) else:
self.readers.pop(fileno, None)
write = write or self.writers.get(fileno)
if write is not None:
self.writers[fileno] = write
else:
self.writers.pop(fileno, None)
exc = exc or self.excs.get(fileno)
if exc is not None:
self.excs[fileno] = exc
else:
self.excs.pop(fileno, None)
self.waiters_by_greenlet[greenlet.getcurrent()] = fileno self.waiters_by_greenlet[greenlet.getcurrent()] = fileno
def remove_descriptor(self, fileno): def remove_descriptor(self, fileno):