[Checkins] SVN: ZODB/trunk/src/ZEO/zrpc/connection.py Bug Fixed: Improved the the ZEO client shutdown support to try to

Jim Fulton jim at zope.com
Fri Aug 29 08:44:35 EDT 2008


Log message for revision 90583:
  Bug Fixed: Improved the the ZEO client shutdown support to try to
  avoid spurious errors on exit, especially for scripts, such as zeopack.
  

Changed:
  U   ZODB/trunk/src/ZEO/zrpc/connection.py

-=-
Modified: ZODB/trunk/src/ZEO/zrpc/connection.py
===================================================================
--- ZODB/trunk/src/ZEO/zrpc/connection.py	2008-08-29 12:30:00 UTC (rev 90582)
+++ ZODB/trunk/src/ZEO/zrpc/connection.py	2008-08-29 12:44:34 UTC (rev 90583)
@@ -40,8 +40,16 @@
 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
 
@@ -49,8 +57,11 @@
     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
@@ -71,17 +82,23 @@
                         # 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):
-                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):
                         # Send a heartbeat message as a reply to a
                         # non-existent message id.
@@ -127,11 +144,14 @@
                     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()



More information about the Checkins mailing list