From f97e82937f8a4e14df939007abacfa252ad09fc8 Mon Sep 17 00:00:00 2001 From: Giampaolo Rodola' Date: Thu, 20 Mar 2014 21:43:41 +0100 Subject: Fix issue 18931: selectors module now supports /dev/poll on Solaris. --- 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 index 98377c8..980a398 100644 --- a/Doc/library/selectors.rst +++ b/Doc/library/selectors.rst @@ -45,6 +45,7 @@ Classes hierarchy:: +-- SelectSelector +-- PollSelector +-- EpollSelector + +-- DevpollSelector +-- KqueueSelector @@ -207,6 +208,16 @@ below: 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 @@ if hasattr(select, 'epoll'): 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 @@ if hasattr(select, 'kqueue'): 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 @@ class KqueueSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn): 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 @@ Core and Builtins 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. -- cgit v0.12