Commit f9805766 authored by Jim Fulton's avatar Jim Fulton

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
parent 41ef3124
......@@ -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)
==================
......
......@@ -1227,6 +1227,34 @@ def runzeo_without_configfile():
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,
......
......@@ -17,6 +17,7 @@ import types
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 @@ class Dispatcher(asyncore.dispatcher):
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))
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment