Index: test/engine/pool.py
===================================================================
--- test/engine/pool.py	(revision 1836)
+++ test/engine/pool.py	(working copy)
@@ -159,6 +159,27 @@
         c3= p.connect()
         assert id(c3.connection) != c_id
     
+    def test_cursors(self):
+        dbapi = MockDBAPI()
+        p = pool.QueuePool(creator = lambda: dbapi.connect('foo.db'), pool_size = 3, max_overflow = 0, use_threadlocal = False, echo=True)
+        conn = p.connect()
+        c1 = conn.cursor()
+        c2 = conn.cursor()
+        conn = None
+        assert p.checkedout() == 1
+        c1 = c2 = None
+        assert p.checkedout() == 0
+        
+        conn = p.connect()
+        c1 = conn.cursor()
+        c2 = conn.cursor()
+        try:
+            conn.close()
+            assert False
+        except exceptions.InvalidRequestError:
+            assert True
+        
+        
     def test_invalidate(self):
         dbapi = MockDBAPI()
         p = pool.QueuePool(creator = lambda: dbapi.connect('foo.db'), pool_size = 1, max_overflow = 0, use_threadlocal = False, echo=True)
Index: lib/sqlalchemy/pool.py
===================================================================
--- lib/sqlalchemy/pool.py	(revision 1859)
+++ lib/sqlalchemy/pool.py	(working copy)
@@ -168,6 +168,7 @@
     """proxies a DBAPI connection object and provides return-on-dereference support"""
     def __init__(self, pool):
         self._threadfairy = _ThreadFairy(self)
+        self.cursors = weakref.WeakKeyDictionary()
         self.__pool = pool
         self.__counter = 0
         try:
@@ -182,6 +183,7 @@
     def invalidate(self):
         self._connection_record.invalidate()
         self.connection = None
+        self.cursors = None
         self._close()
     def cursor(self, *args, **kwargs):
         try:
@@ -196,6 +198,9 @@
             raise "this connection is closed"
         self.__counter +=1
         return self    
+    def close_open_cursors(self):
+        for c in list(self.cursors):
+            c.close()
     def close(self):
         self.__counter -=1
         if self.__counter == 0:
@@ -203,6 +208,8 @@
     def __del__(self):
         self._close()
     def _close(self):
+        if len(self.cursors):
+            raise exceptions.InvalidRequestError("This connection still has %d open cursors" % len(self.cursors))
         if self.connection is not None:
             try:
                 self.connection.rollback()
@@ -219,7 +226,12 @@
 class _CursorFairy(object):
     def __init__(self, parent, cursor):
         self.__parent = parent
+        self.__parent.cursors[self]=True
         self.cursor = cursor
+    def close(self):
+        if self in self.__parent.cursors:
+            del self.__parent.cursors[self]
+            self.cursor.close()
     def __getattr__(self, key):
         return getattr(self.cursor, key)
 
Index: lib/sqlalchemy/engine/base.py
===================================================================
--- lib/sqlalchemy/engine/base.py	(revision 1869)
+++ lib/sqlalchemy/engine/base.py	(working copy)
@@ -211,6 +211,7 @@
         if self.__engine.echo:
             self.__engine.log("ROLLBACK")
         self.__engine.dialect.do_rollback(self.connection)
+        self.__connection.close_open_cursors()
         self.__transaction = None
     def _commit_impl(self):
         if self.__engine.echo:
