[Zodb-checkins] SVN: ZODB/trunk/src/ZEO/ Changed close to use the asyncore thread to try to avoid a race and

Jim Fulton jim at zope.com
Tue Dec 22 15:28:07 EST 2009


Log message for revision 106930:
  Changed close to use the asyncore thread to try to avoid a race and
  breaking the client loop.
  

Changed:
  U   ZODB/trunk/src/ZEO/ClientStorage.py
  U   ZODB/trunk/src/ZEO/tests/testZEO.py

-=-
Modified: ZODB/trunk/src/ZEO/ClientStorage.py
===================================================================
--- ZODB/trunk/src/ZEO/ClientStorage.py	2009-12-22 20:28:05 UTC (rev 106929)
+++ ZODB/trunk/src/ZEO/ClientStorage.py	2009-12-22 20:28:07 UTC (rev 106930)
@@ -442,11 +442,20 @@
             logger.info("%s Waiting for cache verification to finish",
                         self.__name__)
 
-    def close(self):
-        """Storage API: finalize the storage, releasing external resources."""
+    def close(self, kill=False):
+        "Storage API: finalize the storage, releasing external resources."
         if self._rpc_mgr is not None:
             self._rpc_mgr.close()
             self._rpc_mgr = None
+
+        if (self._connection is not None) and not kill:
+            event = threading.Event()
+            self._connection.trigger.pull_trigger(lambda: self._close(event))
+            event.wait(9)
+        else:
+            self._close()
+
+    def _close(self, event=None):
         if self._connection is not None:
             self._connection.register_object(None) # Don't call me!
             self._connection.close()
@@ -462,6 +471,9 @@
         if self._check_blob_size_thread is not None:
             self._check_blob_size_thread.join()
 
+        if event is not None:
+            event.set()
+
     _check_blob_size_thread = None
     def _check_blob_size(self, bytes=None):
         if self._blob_cache_size is None:

Modified: ZODB/trunk/src/ZEO/tests/testZEO.py
===================================================================
--- ZODB/trunk/src/ZEO/tests/testZEO.py	2009-12-22 20:28:05 UTC (rev 106929)
+++ ZODB/trunk/src/ZEO/tests/testZEO.py	2009-12-22 20:28:07 UTC (rev 106930)
@@ -951,6 +951,8 @@
     ...         pass
     ...     def close(self):
     ...         print 'connection closed'
+    ...     trigger = property(lambda self: self)
+    ...     pull_trigger = lambda self, func: func()
 
     >>> class ConnectionManager:
     ...     def __init__(self, addr, client, tmin, tmax):
@@ -1228,6 +1230,35 @@
     testing exit immediately
     """
 
+def close_client_storage_w_invalidations():
+    r"""
+Invalidations could cause errors when closing client storages,
+
+    >>> addr, _ = start_server()
+    >>> writing = threading.Event()
+    >>> def mad_write_thread():
+    ...     global writing
+    ...     conn = ZEO.connection(addr)
+    ...     writing.set()
+    ...     while writing.isSet():
+    ...         conn.root.x = 1
+    ...         transaction.commit()
+    ...     conn.close()
+
+    >>> thread = threading.Thread(target=mad_write_thread)
+    >>> thread.setDaemon(True)
+    >>> thread.start()
+    >>> writing.wait()
+    >>> time.sleep(.01)
+    >>> for i in range(10):
+    ...     conn = ZEO.connection(addr)
+    ...     _ = conn._storage.load('\0'*8)
+    ...     conn.close()
+
+    >>> writing.clear()
+    >>> thread.join(1)
+    """
+
 slow_test_classes = [
     BlobAdaptedFileStorageTests, BlobWritableCacheTests,
     DemoStorageTests, FileStorageTests, MappingStorageTests,



More information about the Zodb-checkins mailing list