Commit 96933dd7 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 d457f745
...@@ -40,7 +40,15 @@ client_timeout_count = 0 # for testing ...@@ -40,7 +40,15 @@ client_timeout_count = 0 # for testing
client_map = {} client_map = {}
client_trigger = trigger(client_map) client_trigger = trigger(client_map)
client_logger = logging.getLogger('ZEO.zrpc.client_loop') 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(): def client_loop():
map = client_map map = client_map
...@@ -49,8 +57,11 @@ def client_loop(): ...@@ -49,8 +57,11 @@ def client_loop():
write = asyncore.write write = asyncore.write
_exception = asyncore._exception _exception = asyncore._exception
loop_failures = 0 loop_failures = 0
client_exit_event.clear()
global client_running
client_running = True
while map: while client_running and map:
try: try:
# The next two lines intentionally don't use # The next two lines intentionally don't use
...@@ -71,17 +82,23 @@ def client_loop(): ...@@ -71,17 +82,23 @@ def client_loop():
# case by looking for entries in r and w that # case by looking for entries in r and w that
# are not in the socket map. # 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 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 continue
raise raise
else: else:
continue continue
if not client_running:
break
if not (r or w or e): if not (r or w or e):
for obj in client_map.itervalues(): # The line intentionally doesn't use iterators. Other
# threads can close dispatchers, causeing the socket
# map to shrink.
for obj in map.values():
if isinstance(obj, Connection): if isinstance(obj, Connection):
# Send a heartbeat message as a reply to a # Send a heartbeat message as a reply to a
# non-existent message id. # non-existent message id.
...@@ -127,11 +144,14 @@ def client_loop(): ...@@ -127,11 +144,14 @@ def client_loop():
except: except:
map.pop(fd, None) map.pop(fd, None)
try: try:
client_logger.critical("Couldn't close a dispatcher.", client_logger.critical(
exc_info=sys.exc_info()) "Couldn't close a dispatcher.",
exc_info=sys.exc_info())
except: except:
pass pass
client_exit_event.set()
client_thread = threading.Thread(target=client_loop) client_thread = threading.Thread(target=client_loop)
client_thread.setDaemon(True) client_thread.setDaemon(True)
client_thread.start() 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