From 757d1ff7a01a49746abea1104cc0a0c267cd7312 Mon Sep 17 00:00:00 2001 From: "which.linden" Date: Thu, 3 Jul 2008 19:41:39 -0700 Subject: [PATCH] [svn r134] Fixes for some interesting issues discovered only after our count of unit tests using database connections crested 100. --- eventlet/coros.py | 18 +++++++++++++++++- eventlet/db_pool.py | 16 ++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/eventlet/coros.py b/eventlet/coros.py index 28810a3..a918d11 100644 --- a/eventlet/coros.py +++ b/eventlet/coros.py @@ -423,14 +423,30 @@ class CoroutinePool(pools.Pool): try: while True: recvd = sender.wait() + # Delete the sender's result here because the very + # first event through the loop is referenced by + # spawn_startup, and therefore is not itself deleted. + # This means that we have to free up its argument + # because otherwise said argument persists in memory + # forever. This is generally only a problem in unit + # tests. + sender._result = NOT_USED + sender = event() (evt, func, args, kw) = recvd self._safe_apply(evt, func, args, kw) + # Likewise, delete these variables or else they will + # be referenced by this frame until replaced by the + # next recvd, which may or may not be a long time from + # now. + del evt, func, args, kw, recvd + api.get_hub().runloop.cancel_timers(api.getcurrent()) self.put(sender) finally: # if we get here, something broke badly, and all we can really - # do is try to keep the pool from leaking items + # do is try to keep the pool from leaking items. + # Shouldn't even try to print the exception. self.put(self.create()) def _safe_apply(self, evt, func, args, kw): diff --git a/eventlet/db_pool.py b/eventlet/db_pool.py index 3c91793..aefe5f8 100644 --- a/eventlet/db_pool.py +++ b/eventlet/db_pool.py @@ -91,6 +91,8 @@ class BaseConnectionPool(Pool): # it's dead or None try: conn.rollback() + except KeyboardInterrupt: + raise except AttributeError, e: # this means it's already been destroyed, so we don't need to print anything conn = None @@ -113,6 +115,20 @@ class BaseConnectionPool(Pool): super(BaseConnectionPool, self).put(conn) else: self.current_size -= 1 + + def clear(self): + """ Close all connections that this pool still holds a reference to, leaving it empty.""" + for conn in self.free_items: + try: + conn.close() + except KeyboardInterrupt: + raise + except: + pass # even if stuff happens here, we still want to at least try to close all the other connections + self.free_items.clear() + + def __del__(self): + self.clear() class SaranwrappedConnectionPool(BaseConnectionPool):