diff options
author | Yury Selivanov <yury@magic.io> | 2016-09-15 23:31:33 (GMT) |
---|---|---|
committer | Yury Selivanov <yury@magic.io> | 2016-09-15 23:31:33 (GMT) |
commit | 993b6f5c7ba072ca58398500570da6e16489f277 (patch) | |
tree | 25288cd28d2b4c4e88700f57d87c36d41bc25460 | |
parent | 732ba01259e805ce6184182e9c26d1a679e0e3b2 (diff) | |
parent | 525aedc5fae90e5195adb2d34ec33f1a773540fc (diff) | |
download | cpython-993b6f5c7ba072ca58398500570da6e16489f277.zip cpython-993b6f5c7ba072ca58398500570da6e16489f277.tar.gz cpython-993b6f5c7ba072ca58398500570da6e16489f277.tar.bz2 |
Merge 3.5 (issue #27759)
-rw-r--r-- | Lib/selectors.py | 26 | ||||
-rw-r--r-- | Lib/test/test_selectors.py | 23 | ||||
-rw-r--r-- | Misc/NEWS | 3 |
3 files changed, 43 insertions, 9 deletions
diff --git a/Lib/selectors.py b/Lib/selectors.py index d8769e3..89680a2 100644 --- a/Lib/selectors.py +++ b/Lib/selectors.py @@ -408,7 +408,11 @@ if hasattr(select, 'epoll'): epoll_events |= select.EPOLLIN if events & EVENT_WRITE: epoll_events |= select.EPOLLOUT - self._epoll.register(key.fd, epoll_events) + try: + self._epoll.register(key.fd, epoll_events) + except BaseException: + super().unregister(fileobj) + raise return key def unregister(self, fileobj): @@ -530,14 +534,18 @@ if hasattr(select, 'kqueue'): def register(self, fileobj, events, data=None): key = super().register(fileobj, events, data) - if events & EVENT_READ: - kev = select.kevent(key.fd, select.KQ_FILTER_READ, - select.KQ_EV_ADD) - self._kqueue.control([kev], 0, 0) - if events & EVENT_WRITE: - kev = select.kevent(key.fd, select.KQ_FILTER_WRITE, - select.KQ_EV_ADD) - self._kqueue.control([kev], 0, 0) + try: + if events & EVENT_READ: + kev = select.kevent(key.fd, select.KQ_FILTER_READ, + select.KQ_EV_ADD) + self._kqueue.control([kev], 0, 0) + if events & EVENT_WRITE: + kev = select.kevent(key.fd, select.KQ_FILTER_WRITE, + select.KQ_EV_ADD) + self._kqueue.control([kev], 0, 0) + except BaseException: + super().unregister(fileobj) + raise return key def unregister(self, fileobj): diff --git a/Lib/test/test_selectors.py b/Lib/test/test_selectors.py index 454c17b..852b2fe 100644 --- a/Lib/test/test_selectors.py +++ b/Lib/test/test_selectors.py @@ -9,6 +9,7 @@ from test import support from time import sleep import unittest import unittest.mock +import tempfile from time import monotonic as time try: import resource @@ -475,6 +476,16 @@ class EpollSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn): SELECTOR = getattr(selectors, 'EpollSelector', None) + def test_register_file(self): + # epoll(7) returns EPERM when given a file to watch + s = self.SELECTOR() + with tempfile.NamedTemporaryFile() as f: + with self.assertRaises(IOError): + s.register(f, selectors.EVENT_READ) + # the SelectorKey has been removed + with self.assertRaises(KeyError): + s.get_key(f) + @unittest.skipUnless(hasattr(selectors, 'KqueueSelector'), "Test needs selectors.KqueueSelector)") @@ -482,6 +493,18 @@ class KqueueSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn): SELECTOR = getattr(selectors, 'KqueueSelector', None) + def test_register_bad_fd(self): + # a file descriptor that's been closed should raise an OSError + # with EBADF + s = self.SELECTOR() + bad_f = support.make_bad_fd() + with self.assertRaises(OSError) as cm: + s.register(bad_f, selectors.EVENT_READ) + self.assertEqual(cm.exception.errno, errno.EBADF) + # the SelectorKey has been removed + with self.assertRaises(KeyError): + s.get_key(bad_f) + @unittest.skipUnless(hasattr(selectors, 'DevpollSelector'), "Test needs selectors.DevpollSelector") @@ -46,6 +46,9 @@ Library - Issue #28176: Fix callbacks race in asyncio.SelectorLoop.sock_connect. +- Issue #27759: Fix selectors incorrectly retain invalid file descriptors. + Patch by Mark Williams. + Build ----- |