[Zodb-checkins] SVN: ZODB/branches/3.9/src/ On Mac OS X, clients that connected and disconnected quickly could

Jim Fulton jim at zope.com
Tue Apr 27 16:23:13 EDT 2010


Log message for revision 111511:
  On Mac OS X, clients that connected and disconnected quickly could
  cause a ZEO server to stop accepting connections, due to a failure
  to catch errors in the initial part of the connection process.
  
  The failure to properly handle exceptions while accepting
  connections is potentially problematic on other platforms.
  
  Fixes: https://bugs.launchpad.net/zodb/+bug/135108
  

Changed:
  U   ZODB/branches/3.9/src/CHANGES.txt
  U   ZODB/branches/3.9/src/ZEO/tests/testZEO.py
  U   ZODB/branches/3.9/src/ZEO/zrpc/server.py

-=-
Modified: ZODB/branches/3.9/src/CHANGES.txt
===================================================================
--- ZODB/branches/3.9/src/CHANGES.txt	2010-04-27 18:35:21 UTC (rev 111510)
+++ ZODB/branches/3.9/src/CHANGES.txt	2010-04-27 20:23:12 UTC (rev 111511)
@@ -2,6 +2,21 @@
  Change History
 ================
 
+3.9.6 (unreleased)
+==================
+
+Bugs Fixed
+----------
+
+- On Mac OS X, clients that connected and disconnected quickly could
+  cause a ZEO server to stop accepting connections, due to a failure
+  to catch errors in the initial part of the connection process.
+
+  The failure to properly handle exceptions while accepting
+  connections is potentially problematic on other platforms.
+
+  Fixes: https://bugs.launchpad.net/zodb/+bug/135108
+
 3.9.5 (2010-04-23)
 ==================
 

Modified: ZODB/branches/3.9/src/ZEO/tests/testZEO.py
===================================================================
--- ZODB/branches/3.9/src/ZEO/tests/testZEO.py	2010-04-27 18:35:21 UTC (rev 111510)
+++ ZODB/branches/3.9/src/ZEO/tests/testZEO.py	2010-04-27 20:23:12 UTC (rev 111511)
@@ -1227,6 +1227,34 @@
     testing exit immediately
     """
 
+def quick_close_doesnt_kill_server():
+    r"""
+
+    Start a server:
+
+    >>> addr, _ = start_server()
+
+    Now connect and immediately disconnect. This caused the server to
+    die in the past:
+
+    >>> import socket, struct
+    >>> for i in range(5):
+    ...     s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    ...     s.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
+    ...                  struct.pack('ii', 1, 0))
+    ...     s.connect(addr)
+    ...     s.close()
+
+    Now we should be able to connect as normal:
+
+    >>> db = ZEO.DB(addr)
+    >>> db.storage.is_connected()
+    True
+
+    >>> db.close()
+
+    """
+
 slow_test_classes = [
     BlobAdaptedFileStorageTests, BlobWritableCacheTests,
     DemoStorageTests, FileStorageTests, MappingStorageTests,

Modified: ZODB/branches/3.9/src/ZEO/zrpc/server.py
===================================================================
--- ZODB/branches/3.9/src/ZEO/zrpc/server.py	2010-04-27 18:35:21 UTC (rev 111510)
+++ ZODB/branches/3.9/src/ZEO/zrpc/server.py	2010-04-27 20:23:12 UTC (rev 111511)
@@ -17,6 +17,7 @@
 
 from ZEO.zrpc.connection import Connection
 from ZEO.zrpc.log import log
+import ZEO.zrpc.log
 import logging
 
 # Export the main asyncore loop
@@ -54,5 +55,23 @@
         except socket.error, msg:
             log("accepted failed: %s" % msg)
             return
-        c = self.factory(sock, addr)
-        log("connect from %s: %s" % (repr(addr), c))
+
+        # We could short-circuit the attempt below in some edge cases
+        # and avoid a log message by checking for addr being None.
+        # Unfortunately, our test for the code below,
+        # quick_close_doesnt_kill_server, causes addr to be None and
+        # we'd have to write a test for the non-None case, which is
+        # *even* harder to provoke. :/ So we'll leave things as they
+        # are for now.
+
+        # It might be better to check whether the socket has been
+        # closed, but I don't see a way to do that. :(
+
+        try:
+            c = self.factory(sock, addr)
+        except:
+            if sock.fileno() in asyncore.socket_map:
+                del asyncore.socket_map[sock.fileno()]
+            ZEO.zrpc.log.logger.exception("Error in handle_accept")
+        else:
+            log("connect from %s: %s" % (repr(addr), c))



More information about the Zodb-checkins mailing list