[Zope-Checkins] CVS: ZODB3/ThreadedAsync - LoopCallback.py:1.6
Guido van Rossum
guido@python.org
Tue, 5 Nov 2002 14:31:22 -0500
Update of /cvs-repository/ZODB3/ThreadedAsync
In directory cvs.zope.org:/tmp/cvs-serv10705
Modified Files:
LoopCallback.py
Log Message:
I fixed a bug in asyncore.poll() in Python 2.3; quoting the Python cvs
log:
Fix an old bug in poll(). When a signal is handled while we're
blocked in select(), this will raise select.error with errno set
to EINTR. The except clauses correctly ignores this error, but
the rest of the logic will then call read() for all objects in
select's *input* list of read file descriptors. Then when an
object's read_handler() is naive, it will call recv() on its
socket, which will raise an IOError, and then asyncore decides to
close the socket. To fix this, we simply return in this case.
Rather than incorporating a fixed copy of asyncore.py in Zope2 and
ZODB3, I'm incorporating a fixed copy of just asyncore.poll() in this
file, since we already have a copy of asyncore.loop() here.
=== ZODB3/ThreadedAsync/LoopCallback.py 1.5 => 1.6 ===
--- ZODB3/ThreadedAsync/LoopCallback.py:1.5 Fri Sep 27 16:49:08 2002
+++ ZODB3/ThreadedAsync/LoopCallback.py Tue Nov 5 14:31:21 2002
@@ -34,6 +34,8 @@
import asyncore
import select
import thread
+import time
+from errno import EINTR
_loop_lock = thread.allocate_lock()
_looping = None
@@ -79,6 +81,52 @@
finally:
_loop_lock.release()
+def poll(timeout=0.0, map=None):
+ """A copy of asyncore.poll() with a bug fixed (see comment).
+
+ (asyncore.poll2() and .poll3() don't have this bug.)
+ """
+ if map is None:
+ map = asyncore.socket_map
+ if map:
+ r = []; w = []; e = []
+ for fd, obj in map.items():
+ if obj.readable():
+ r.append(fd)
+ if obj.writable():
+ w.append(fd)
+ if [] == r == w == e:
+ time.sleep(timeout)
+ else:
+ try:
+ r, w, e = select.select(r, w, e, timeout)
+ except select.error, err:
+ if err[0] != EINTR:
+ raise
+ else:
+ # This part is missing in asyncore before Python 2.3
+ return
+
+ for fd in r:
+ obj = map.get(fd)
+ if obj is not None:
+ try:
+ obj.handle_read_event()
+ except asyncore.ExitNow:
+ raise asyncore.ExitNow
+ except:
+ obj.handle_error()
+
+ for fd in w:
+ obj = map.get(fd)
+ if obj is not None:
+ try:
+ obj.handle_write_event()
+ except asyncore.ExitNow:
+ raise asyncore.ExitNow
+ except:
+ obj.handle_error()
+
def loop(timeout=30.0, use_poll=0, map=None):
"""Invoke asyncore mainloop
@@ -92,7 +140,7 @@
else:
poll_fun = asyncore.poll2
else:
- poll_fun = asyncore.poll
+ poll_fun = poll
if map is None:
map = asyncore.socket_map