Commit 5f7145c7 authored by Jim Fulton's avatar Jim Fulton

Bug Fixed: Improved the the ZEO client shutdown support to try to

avoid spurious errors on exit, especially for scripts, such as zeopack.
parent aac4cd4b
......@@ -5,6 +5,9 @@ Whats new in ZODB 3.8.1
Bugs Fixed:
- (beta 5) Improved the the ZEO client shutdown support to try to
avoid spurious errors on exit, especially for scripts, such as zeopack.
- (beta 4) Packing failed for databases containing cross-database references.
- (beta 3) Cross-database references to databases with empty names
......
......@@ -41,7 +41,15 @@ client_timeout_count = 0 # for testing
client_map = {}
client_trigger = trigger(client_map)
client_logger = logging.getLogger('ZEO.zrpc.client_loop')
atexit.register(client_map.clear)
client_exit_event = threading.Event()
client_running = True
def client_exit():
global client_running
client_running = False
client_trigger.pull_trigger()
client_exit_event.wait()
atexit.register(client_exit)
def client_loop():
map = client_map
......@@ -50,8 +58,11 @@ def client_loop():
write = asyncore.write
_exception = asyncore._exception
loop_failures = 0
client_exit_event.clear()
global client_running
client_running = True
while map:
while client_running and map:
try:
# The next two lines intentionally don't use
......@@ -72,20 +83,23 @@ def client_loop():
# case by looking for entries in r and w that
# are not in the socket map.
if [fd for fd in r if fd not in client_map]:
if [fd for fd in r if fd not in map]:
continue
if [fd for fd in w if fd not in client_map]:
if [fd for fd in w if fd not in map]:
continue
raise
else:
continue
if not client_running:
break
if not (r or w or e):
# The line intentionally doesn't use iterators. Other
# threads can close dispatchers, causeing the socket
# map to shrink.
for obj in client_map.values():
for obj in map.values():
if isinstance(obj, Connection):
# Send a heartbeat message as a reply to a
# non-existent message id.
......@@ -131,11 +145,14 @@ def client_loop():
except:
map.pop(fd, None)
try:
client_logger.critical("Couldn't close a dispatcher.",
exc_info=sys.exc_info())
client_logger.critical(
"Couldn't close a dispatcher.",
exc_info=sys.exc_info())
except:
pass
client_exit_event.set()
client_thread = threading.Thread(target=client_loop)
client_thread.setDaemon(True)
client_thread.start()
......
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