[Zodb-checkins] CVS: ZODB3/ThreadedAsync - LoopCallback.py:1.5.2.1

Guido van Rossum guido@python.org
Tue, 12 Nov 2002 08:21:53 -0500


Update of /cvs-repository/ZODB3/ThreadedAsync
In directory cvs.zope.org:/tmp/cvs-serv21856

Modified Files:
      Tag: ZODB3-3_1-branch
	LoopCallback.py 
Log Message:
Added code to ThreadedAsync/LoopCallback.py to work around a bug in
asyncore.py: a handled signal can cause unwanted reads to happen.


=== ZODB3/ThreadedAsync/LoopCallback.py 1.5 => 1.5.2.1 ===
--- ZODB3/ThreadedAsync/LoopCallback.py:1.5	Fri Sep 27 16:49:08 2002
+++ ZODB3/ThreadedAsync/LoopCallback.py	Tue Nov 12 08:21:53 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