]> granicus.if.org Git - python/commitdiff
Issue #18934: multiprocessing: use selectors module.
authorCharles-François Natali <cf.natali@gmail.com>
Thu, 5 Sep 2013 18:46:49 +0000 (20:46 +0200)
committerCharles-François Natali <cf.natali@gmail.com>
Thu, 5 Sep 2013 18:46:49 +0000 (20:46 +0200)
Lib/multiprocessing/connection.py
Lib/multiprocessing/forkserver.py

index 9fbe46deff46aac19586b4e19dfbfefb99e4277f..59fb6640d5bbf76510af2d6a23a59c2d0637449f 100644 (file)
@@ -12,7 +12,6 @@ __all__ = [ 'Client', 'Listener', 'Pipe', 'wait' ]
 import io
 import os
 import sys
-import select
 import socket
 import struct
 import errno
@@ -877,28 +876,7 @@ if sys.platform == 'win32':
 
 else:
 
-    if hasattr(select, 'poll'):
-        def _poll(fds, timeout):
-            if timeout is not None:
-                timeout = int(timeout * 1000)  # timeout is in milliseconds
-            fd_map = {}
-            pollster = select.poll()
-            for fd in fds:
-                pollster.register(fd, select.POLLIN)
-                if hasattr(fd, 'fileno'):
-                    fd_map[fd.fileno()] = fd
-                else:
-                    fd_map[fd] = fd
-            ls = []
-            for fd, event in pollster.poll(timeout):
-                if event & select.POLLNVAL:
-                    raise ValueError('invalid file descriptor %i' % fd)
-                ls.append(fd_map[fd])
-            return ls
-    else:
-        def _poll(fds, timeout):
-            return select.select(fds, [], [], timeout)[0]
-
+    import selectors
 
     def wait(object_list, timeout=None):
         '''
@@ -906,19 +884,22 @@ else:
 
         Returns list of those objects in object_list which are ready/readable.
         '''
-        if timeout is not None:
-            if timeout <= 0:
-                return _poll(object_list, 0)
-            else:
-                deadline = time.time() + timeout
-        while True:
-            try:
-                return _poll(object_list, timeout)
-            except OSError as e:
-                if e.errno != errno.EINTR:
-                    raise
+        with selectors.DefaultSelector() as selector:
+            for obj in object_list:
+                selector.register(obj, selectors.EVENT_READ)
+
             if timeout is not None:
-                timeout = deadline - time.time()
+                deadline = time.time() + timeout
+
+            while True:
+                ready = selector.select(timeout)
+                if ready:
+                    return [key.fileobj for (key, events) in ready]
+                else:
+                    if timeout is not None:
+                        timeout = deadline - time.time()
+                        if timeout < 0:
+                            return ready
 
 #
 # Make connection and socket objects sharable if possible
index 975b15aef8fde9cd8f839a910e901d7d84301dc3..0a237079f15180d1cf93bad3a7fb7e60264f4da8 100644 (file)
@@ -1,6 +1,6 @@
 import errno
 import os
-import select
+import selectors
 import signal
 import socket
 import struct
@@ -149,14 +149,20 @@ def main(listener_fd, alive_r, preload, main_path=None, sys_path=None):
 
     # ignoring SIGCHLD means no need to reap zombie processes
     handler = signal.signal(signal.SIGCHLD, signal.SIG_IGN)
-    with socket.socket(socket.AF_UNIX, fileno=listener_fd) as listener:
+    with socket.socket(socket.AF_UNIX, fileno=listener_fd) as listener, \
+         selectors.DefaultSelector() as selector:
         global _forkserver_address
         _forkserver_address = listener.getsockname()
-        readers = [listener, alive_r]
+
+        selector.register(listener, selectors.EVENT_READ)
+        selector.register(alive_r, selectors.EVENT_READ)
 
         while True:
             try:
-                rfds, wfds, xfds = select.select(readers, [], [])
+                while True:
+                    rfds = [key.fileobj for (key, events) in selector.select()]
+                    if rfds:
+                        break
 
                 if alive_r in rfds:
                     # EOF because no more client processes left