Fix issue 18931: selectors module now supports /dev/poll on Solaris.
diff --git a/Doc/library/selectors.rst b/Doc/library/selectors.rst
index 98377c8..980a398 100644
--- 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
index 9be9225..4e9ae6e 100644
--- 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
index 34edd76..8f83c90 100644
--- a/Lib/test/test_selectors.py
+++ b/Lib/test/test_selectors.py
@@ -441,10 +441,18 @@
     SELECTOR = getattr(selectors, 'KqueueSelector', None)
 
 
+@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
index 479102f..7d1a9d8 100644
--- 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.