[Zope-Checkins] CVS: Releases/Zope/lib/python/ThreadedAsync - LoopCallback.py:1.4.6.1

Guido van Rossum guido@python.org
Tue, 5 Nov 2002 14:55:43 -0500


Update of /cvs-repository/Releases/Zope/lib/python/ThreadedAsync
In directory cvs.zope.org:/tmp/cvs-serv20451/lib/python/ThreadedAsync

Modified Files:
      Tag: Zope-2_6-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.


=== Releases/Zope/lib/python/ThreadedAsync/LoopCallback.py 1.4 => 1.4.6.1 ===
--- Releases/Zope/lib/python/ThreadedAsync/LoopCallback.py:1.4	Wed Aug 14 18:02:00 2002
+++ Releases/Zope/lib/python/ThreadedAsync/LoopCallback.py	Tue Nov  5 14:55:42 2002
@@ -29,11 +29,13 @@
 module is imported, any client of the asyncore module will get
 ThreadedAsync.loop() when it calls asyncore.loop().
 """
-__version__='$Revision$'[11:-2]
+__version__ = '$Revision$'[11:-2]
 
 import asyncore
 import select
 import thread
+import time
+from errno import EINTR
 
 _loop_lock = thread.allocate_lock()
 _looping = None
@@ -79,7 +81,53 @@
     finally:
         _loop_lock.release()
 
-def loop (timeout=30.0, use_poll=0, map=None):
+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
 
     This function functions like the regular asyncore.loop() function
@@ -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
@@ -103,11 +151,10 @@
     _stop_loop()
 
 # Woo hoo!
-asyncore.loop=loop
+asyncore.loop = loop
 
 # What the heck did we just do?
 #
 # Well, the thing is, we want to work with other asyncore aware
 # code. In particular, we don't necessarily want to make someone
 # import this module just to start or loop.
-#