From 135d2ad865f1f6f905b7390d6e379bc5580669cb Mon Sep 17 00:00:00 2001 From: donovan Date: Wed, 25 Jun 2008 15:26:00 -0700 Subject: [PATCH] Fix another common cause of SwitchingToDeadGreenlet or _socketobject is not iterable. Using exc_after to cancel a socket operation would leave the socket's fd in the hub, causing a spurious resumption of that greenlet when the socket operation completed in the future. --- eventlet/api.py | 3 ++- eventlet/hubs/hub.py | 9 +++++++++ eventlet/hubs/libevent.py | 4 +++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/eventlet/api.py b/eventlet/api.py index 265cb8c..e365d0f 100644 --- a/eventlet/api.py +++ b/eventlet/api.py @@ -295,7 +295,8 @@ def exc_after(seconds, exception_object): else: timer.cancel() """ - return call_after(seconds, switch, getcurrent(), None, exception_object) + hub = get_hub() + return call_after(seconds, hub.exc_greenlet, getcurrent(), exception_object) def get_default_hub(): diff --git a/eventlet/hubs/hub.py b/eventlet/hubs/hub.py index f9637bf..d36a248 100644 --- a/eventlet/hubs/hub.py +++ b/eventlet/hubs/hub.py @@ -45,6 +45,7 @@ class BaseHub(object): self.readers = {} self.writers = {} self.excs = {} + self.waiters_by_greenlet = {} self.clock = clock self.greenlet = None @@ -80,11 +81,19 @@ class BaseHub(object): 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) + self.waiters_by_greenlet[greenlet.getcurrent()] = fileno def remove_descriptor(self, fileno): self.readers.pop(fileno, None) self.writers.pop(fileno, None) self.excs.pop(fileno, None) + self.waiters_by_greenlet.pop(greenlet.getcurrent(), None) + + def exc_greenlet(self, gr, exception_object): + fileno = self.waiters_by_greenlet.pop(gr, None) + if fileno is not None: + self.remove_descriptor(fileno) + greenlib.switch(gr, None, exception_object) def exc_descriptor(self, fileno): exc = self.excs.get(fileno) diff --git a/eventlet/hubs/libevent.py b/eventlet/hubs/libevent.py index a5b4afd..4e5c643 100644 --- a/eventlet/hubs/libevent.py +++ b/eventlet/hubs/libevent.py @@ -59,7 +59,6 @@ class Hub(hub.BaseHub): sig = event.signal(signal.SIGINT, self.signal_received, signal.SIGINT) sig.add() - def add_descriptor(self, fileno, read=None, write=None, exc=None): if read: evt = event.read(fileno, read, fileno) @@ -74,12 +73,15 @@ class Hub(hub.BaseHub): if exc: self.excs[fileno] = exc + self.waiters_by_greenlet[greenlet.getcurrent()] = fileno + def remove_descriptor(self, fileno): for queue in (self.readers, self.writers): tpl = queue.pop(fileno, None) if tpl is not None: tpl[0].delete() self.excs.pop(fileno, None) + self.waiters_by_greenlet.pop(greenlet.getcurrent(), None) def abort(self): super(Hub, self).abort()