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)
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
=====

View File

@@ -78,10 +78,21 @@ class BaseHub(object):
so the exc callback happens instead of the respective read or write
callback.
"""
self.readers[fileno] = read or self.readers.get(fileno)
self.writers[fileno] = write or self.writers.get(fileno)
self.excs[fileno] = exc or self.excs.get(fileno)
read = read or self.readers.get(fileno)
if read is not None:
self.readers[fileno] = read
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
def remove_descriptor(self, fileno):