Author: Brian Kearns <[email protected]>
Branch: stdlib-2.7.6
Changeset: r69647:b659126507d5
Date: 2014-03-03 18:55 -0500
http://bitbucket.org/pypy/pypy/changeset/b659126507d5/

Log:    raise exception on concurrent calls to poll() (cpython issue8865)

diff --git a/pypy/module/select/interp_select.py 
b/pypy/module/select/interp_select.py
--- a/pypy/module/select/interp_select.py
+++ b/pypy/module/select/interp_select.py
@@ -19,6 +19,7 @@
 class Poll(W_Root):
     def __init__(self):
         self.fddict = {}
+        self.running = False
 
     @unwrap_spec(events="c_short")
     def register(self, space, w_fd, events=defaultevents):
@@ -41,7 +42,7 @@
             raise OperationError(space.w_KeyError,
                                  space.wrap(fd)) # XXX should this maybe be 
w_fd?
 
-    @unwrap_spec(w_timeout = WrappedDefault(None))
+    @unwrap_spec(w_timeout=WrappedDefault(None))
     def poll(self, space, w_timeout):
         if space.is_w(w_timeout, space.w_None):
             timeout = -1
@@ -56,6 +57,9 @@
                     "timeout must be an integer or None")
             timeout = space.c_int_w(w_timeout)
 
+        if self.running:
+            raise oefmt(space.w_RuntimeError, "concurrent poll() invocation")
+        self.running = True
         try:
             retval = rpoll.poll(self.fddict, timeout)
         except rpoll.PollError, e:
@@ -64,6 +68,8 @@
             raise OperationError(w_errortype,
                                  space.newtuple([space.wrap(e.errno),
                                                  space.wrap(message)]))
+        finally:
+            self.running = False
 
         retval_w = []
         for fd, revents in retval:
diff --git a/pypy/module/select/test/test_select.py 
b/pypy/module/select/test/test_select.py
--- a/pypy/module/select/test/test_select.py
+++ b/pypy/module/select/test/test_select.py
@@ -1,5 +1,4 @@
 import sys
-
 import py
 
 from pypy.interpreter.error import OperationError
@@ -234,7 +233,7 @@
 class AppTestSelectWithPipes(_AppTestSelect):
     "Use a pipe to get pairs of file descriptors"
     spaceconfig = {
-        "usemodules": ["select", "rctime"]
+        "usemodules": ["select", "rctime", "thread"]
     }
 
     def setup_class(cls):
@@ -258,6 +257,37 @@
         s1, s2 = os.pipe()
         return FileAsSocket(s1), FileAsSocket(s2)
 
+    def test_poll_threaded(self):
+        import os, select, threading, time
+        if not hasattr(select, 'poll'):
+            skip("no select.poll() on this platform")
+        r, w = os.pipe()
+        rfds = [os.dup(r) for _ in range(10)]
+        try:
+            pollster = select.poll()
+            for fd in rfds:
+                pollster.register(fd, select.POLLIN)
+
+            t = threading.Thread(target=pollster.poll)
+            t.start()
+            try:
+                time.sleep(0.5); print '',  # print to release GIL untranslated
+                # trigger ufds array reallocation
+                for fd in rfds:
+                    pollster.unregister(fd)
+                pollster.register(w, select.POLLOUT)
+                exc = raises(RuntimeError, pollster.poll)
+                assert exc.value[0] == 'concurrent poll() invocation'
+            finally:
+                # and make the call to poll() from the thread return
+                os.write(w, b'spam')
+                t.join()
+        finally:
+            os.close(r)
+            os.close(w)
+            for fd in rfds:
+                os.close(fd)
+
 
 class AppTestSelectWithSockets(_AppTestSelect):
     """Same tests with connected sockets.
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to