Commit 063fe8e3 authored by Tim Peters's avatar Tim Peters

Duplicate asyncore.loop again, this time a meld of 2.3's and 2.4's, in

an attempt to be compatible with both.
parent e75e2c06
......@@ -89,6 +89,13 @@ FileStorage
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
......
......@@ -29,7 +29,10 @@ socket map as its first argument.
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 @@ def remove_loop_callback(callback):
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 @@ def loop(*args, **kws):
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 @@ def loop(*args, **kws):
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
......
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