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:
2
NEWS
2
NEWS
@@ -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
|
||||
=====
|
||||
|
||||
|
@@ -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):
|
||||
|
Reference in New Issue
Block a user