[Zodb-checkins] SVN: ZODB/branches/3.4/ Duplicate asyncore.loop again, this time a meld of 2.3's and 2.4's, in

Tim Peters tim.one at comcast.net
Tue Jul 19 12:38:30 EDT 2005


Log message for revision 37333:
  Duplicate asyncore.loop again, this time a meld of 2.3's and 2.4's, in
  an attempt to be compatible with both.
  

Changed:
  U   ZODB/branches/3.4/NEWS.txt
  U   ZODB/branches/3.4/src/ThreadedAsync/LoopCallback.py

-=-
Modified: ZODB/branches/3.4/NEWS.txt
===================================================================
--- ZODB/branches/3.4/NEWS.txt	2005-07-19 14:22:35 UTC (rev 37332)
+++ ZODB/branches/3.4/NEWS.txt	2005-07-19 16:38:00 UTC (rev 37333)
@@ -89,6 +89,13 @@
 ThreadedAsync.LoopCallback
 --------------------------
 
+- (3.4.1a6) This once again physically replaces Python's ``asyncore.loop``
+  function with its own loop function, because it turns out Zope relied on
+  the seemingly unused ``LoopCallback.exit_status`` global, which was
+  removed in the change described below.  Python's ``asyncore.loop`` is again
+  not invoked, so any breakpoints or debugging prints added to that are again
+  "lost".
+
 - (3.4.1a1) This replaces Python's ``asyncore.loop`` function with its own,
   in order to get notified when ``loop()`` is first called.  The signature of
   ``asyncore.loop`` changed in Python 2.4, but ``LoopCallback.loop``'s

Modified: ZODB/branches/3.4/src/ThreadedAsync/LoopCallback.py
===================================================================
--- ZODB/branches/3.4/src/ThreadedAsync/LoopCallback.py	2005-07-19 14:22:35 UTC (rev 37332)
+++ ZODB/branches/3.4/src/ThreadedAsync/LoopCallback.py	2005-07-19 16:38:00 UTC (rev 37333)
@@ -29,7 +29,10 @@
 import asyncore
 import thread
 
-_original_asyncore_loop = asyncore.loop
+# Zope pokes a non-None value into exit_status when it wants the loop()
+# function to exit.  Indeed, there appears to be no other way to tell
+# Zope3 to shut down.
+exit_status = None
 
 _loop_lock = thread.allocate_lock()
 _looping = None # changes to socket map when loop() starts
@@ -66,14 +69,36 @@
             del _loop_callbacks[i]
             return
 
-# Caution:  the signature of asyncore.loop changed in Python 2.4.
-# That's why we use `args` and `kws` instead of spelling out the
-# "intended" arguments.  Since we _replace_ asyncore.loop with this
-# loop(), we need to be compatible with all signatures.
-def loop(*args, **kws):
+# Because of the exit_status magic, we can't just invoke asyncore.loop(),
+# and that's a shame.
+# The signature of asyncore.loop changed between Python 2.3 and 2.4, and
+# this loop() has 2.4's signature, which added the optional `count` argument.
+# Since we physically replace asyncore.loop with this `loop`, and want
+# compatibility with both Pythons, we need to support the most recent
+# signature.  Applications running under 2.3 should (of course) avoid using
+# the `count` argument, since 2.3 doesn't have it.
+def loop(timeout=30.0, use_poll=False, map=None, count=None):
     global _looping
+    global exit_status
 
-    map = kws.get("map", asyncore.socket_map)
+    exit_status = None
+
+    if map is None:
+        map = asyncore.socket_map
+
+    # This section is taken from Python 2.3's asyncore.loop, and is more
+    # elaborate than the corresponding section of 2.4's:  in 2.4 poll2 and
+    # poll3 are aliases for the same function, in 2.3 they're different
+    # functions.
+    if use_poll:
+        if hasattr(select, 'poll'):
+            poll_fun = asyncore.poll3
+        else:
+            poll_fun = asyncore.poll2
+    else:
+        poll_fun = asyncore.poll
+
+    # The loop is about to start:  invoke any registered callbacks.
     _loop_lock.acquire()
     try:
         _looping = map
@@ -83,7 +108,15 @@
     finally:
         _loop_lock.release()
 
-    result = _original_asyncore_loop(*args, **kws)
+    # Run the loop.  This is 2.4's logic, with the addition that we stop
+    # if/when this module's exit_status global is set to a non-None value.
+    if count is None:
+        while map and exit_status is None:
+            poll_fun(timeout, map)
+    else:
+        while map and count > 0 and exit_status is None:
+            poll_fun(timeout, map)
+            count -= 1
 
     _loop_lock.acquire()
     try:
@@ -91,16 +124,15 @@
     finally:
         _loop_lock.release()
 
-    return result
-
-
 # Evil:  rebind asyncore.loop to the above loop() function.
 #
 # Code should explicitly call ThreadedAsync.loop() instead of asyncore.loop().
 # Most of ZODB has been fixed, but ripping this out may break 3rd party code.
-# Maybe we should issue a warning and let it continue for a while.  Or
-# maybe we should get rid of this mechanism entirely, and have each ZEO
-# piece that needs one run its own asyncore loop in its own thread.
+# Maybe we should issue a warning and let it continue for a while (NOTE:  code
+# to raise DeprecationWarning was written but got commented out below; don't
+# know why it got commented out).  Or maybe we should get rid of this
+# mechanism entirely, and have each piece that needs one run its own asyncore
+# loop in its own thread.
 
 ##def deprecated_loop(*args, **kws):
 ##    import warnings



More information about the Zodb-checkins mailing list