[Python-checkins] cpython: Fix issue 18931: selectors module now supports /dev/poll on Solaris.

giampaolo.rodola python-checkins at python.org
Thu Mar 20 21:54:40 CET 2014


http://hg.python.org/cpython/rev/0a51a516bc70
changeset:   89890:0a51a516bc70
parent:      89872:2e4692a762d5
user:        Giampaolo Rodola' <g.rodola at gmail.com>
date:        Thu Mar 20 21:43:41 2014 +0100
summary:
  Fix issue 18931: selectors module now supports /dev/poll on Solaris.

files:
  Doc/library/selectors.rst  |  11 ++++
  Lib/selectors.py           |  62 +++++++++++++++++++++++++-
  Lib/test/test_selectors.py |  10 +++-
  Misc/NEWS                  |   3 +
  4 files changed, 84 insertions(+), 2 deletions(-)


diff --git a/Doc/library/selectors.rst b/Doc/library/selectors.rst
--- a/Doc/library/selectors.rst
+++ b/Doc/library/selectors.rst
@@ -45,6 +45,7 @@
    +-- SelectSelector
    +-- PollSelector
    +-- EpollSelector
+   +-- DevpollSelector
    +-- KqueueSelector
 
 
@@ -207,6 +208,16 @@
       This returns the file descriptor used by the underlying
       :func:`select.epoll` object.
 
+.. class:: DevpollSelector()
+
+   :func:`select.devpoll`-based selector.
+
+   .. method:: fileno()
+
+      This returns the file descriptor used by the underlying
+      :func:`select.devpoll` object.
+
+.. versionadded:: 3.5
 
 .. class:: KqueueSelector()
 
diff --git a/Lib/selectors.py b/Lib/selectors.py
--- a/Lib/selectors.py
+++ b/Lib/selectors.py
@@ -441,6 +441,64 @@
             super().close()
 
 
+if hasattr(select, 'devpoll'):
+
+    class DevpollSelector(_BaseSelectorImpl):
+        """Solaris /dev/poll selector."""
+
+        def __init__(self):
+            super().__init__()
+            self._devpoll = select.devpoll()
+
+        def fileno(self):
+            return self._devpoll.fileno()
+
+        def register(self, fileobj, events, data=None):
+            key = super().register(fileobj, events, data)
+            poll_events = 0
+            if events & EVENT_READ:
+                poll_events |= select.POLLIN
+            if events & EVENT_WRITE:
+                poll_events |= select.POLLOUT
+            self._devpoll.register(key.fd, poll_events)
+            return key
+
+        def unregister(self, fileobj):
+            key = super().unregister(fileobj)
+            self._devpoll.unregister(key.fd)
+            return key
+
+        def select(self, timeout=None):
+            if timeout is None:
+                timeout = None
+            elif timeout <= 0:
+                timeout = 0
+            else:
+                # devpoll() has a resolution of 1 millisecond, round away from
+                # zero to wait *at least* timeout seconds.
+                timeout = math.ceil(timeout * 1e3)
+            ready = []
+            try:
+                fd_event_list = self._devpoll.poll(timeout)
+            except InterruptedError:
+                return ready
+            for fd, event in fd_event_list:
+                events = 0
+                if event & ~select.POLLIN:
+                    events |= EVENT_WRITE
+                if event & ~select.POLLOUT:
+                    events |= EVENT_READ
+
+                key = self._key_from_fd(fd)
+                if key:
+                    ready.append((key, events & key.events))
+            return ready
+
+        def close(self):
+            self._devpoll.close()
+            super().close()
+
+
 if hasattr(select, 'kqueue'):
 
     class KqueueSelector(_BaseSelectorImpl):
@@ -513,12 +571,14 @@
             super().close()
 
 
-# Choose the best implementation: roughly, epoll|kqueue > poll > select.
+# Choose the best implementation: roughly, epoll|kqueue|devpoll > poll > select.
 # select() also can't accept a FD > FD_SETSIZE (usually around 1024)
 if 'KqueueSelector' in globals():
     DefaultSelector = KqueueSelector
 elif 'EpollSelector' in globals():
     DefaultSelector = EpollSelector
+elif 'DevpollSelector' in globals():
+    DefaultSelector = DevpollSelector
 elif 'PollSelector' in globals():
     DefaultSelector = PollSelector
 else:
diff --git a/Lib/test/test_selectors.py b/Lib/test/test_selectors.py
--- a/Lib/test/test_selectors.py
+++ b/Lib/test/test_selectors.py
@@ -441,10 +441,18 @@
     SELECTOR = getattr(selectors, 'KqueueSelector', None)
 
 
+ at unittest.skipUnless(hasattr(selectors, 'DevpollSelector'),
+                     "Test needs selectors.DevpollSelector")
+class DevpollSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn):
+
+    SELECTOR = getattr(selectors, 'DevpollSelector', None)
+
+
+
 def test_main():
     tests = [DefaultSelectorTestCase, SelectSelectorTestCase,
              PollSelectorTestCase, EpollSelectorTestCase,
-             KqueueSelectorTestCase]
+             KqueueSelectorTestCase, DevpollSelectorTestCase]
     support.run_unittest(*tests)
     support.reap_children()
 
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -23,6 +23,9 @@
 Library
 -------
 
+- Issue 18931: selectors module now supports /dev/poll on Solaris.
+  Patch by Giampaolo Rodola'.
+
 - Issue #19977: When the ``LC_TYPE`` locale is the POSIX locale (``C`` locale),
   :py:data:`sys.stdin` and :py:data:`sys.stdout` are now using the
   ``surrogateescape`` error handler, instead of the ``strict`` error handler.

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list