Commit 8228a2b3 authored by Yury Selivanov's avatar Yury Selivanov

Issue #27759: Fix selectors incorrectly retain invalid file descriptors.

Patch by Mark Williams.
parent 14828f5a
...@@ -408,7 +408,11 @@ if hasattr(select, 'epoll'): ...@@ -408,7 +408,11 @@ if hasattr(select, 'epoll'):
epoll_events |= select.EPOLLIN epoll_events |= select.EPOLLIN
if events & EVENT_WRITE: if events & EVENT_WRITE:
epoll_events |= select.EPOLLOUT 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 return key
def unregister(self, fileobj): def unregister(self, fileobj):
...@@ -530,14 +534,18 @@ if hasattr(select, 'kqueue'): ...@@ -530,14 +534,18 @@ if hasattr(select, 'kqueue'):
def register(self, fileobj, events, data=None): def register(self, fileobj, events, data=None):
key = super().register(fileobj, events, data) key = super().register(fileobj, events, data)
if events & EVENT_READ: try:
kev = select.kevent(key.fd, select.KQ_FILTER_READ, if events & EVENT_READ:
select.KQ_EV_ADD) kev = select.kevent(key.fd, select.KQ_FILTER_READ,
self._kqueue.control([kev], 0, 0) select.KQ_EV_ADD)
if events & EVENT_WRITE: self._kqueue.control([kev], 0, 0)
kev = select.kevent(key.fd, select.KQ_FILTER_WRITE, if events & EVENT_WRITE:
select.KQ_EV_ADD) kev = select.kevent(key.fd, select.KQ_FILTER_WRITE,
self._kqueue.control([kev], 0, 0) select.KQ_EV_ADD)
self._kqueue.control([kev], 0, 0)
except BaseException:
super().unregister(fileobj)
raise
return key return key
def unregister(self, fileobj): def unregister(self, fileobj):
......
...@@ -9,6 +9,7 @@ from test import support ...@@ -9,6 +9,7 @@ from test import support
from time import sleep from time import sleep
import unittest import unittest
import unittest.mock import unittest.mock
import tempfile
from time import monotonic as time from time import monotonic as time
try: try:
import resource import resource
...@@ -475,6 +476,16 @@ class EpollSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn): ...@@ -475,6 +476,16 @@ class EpollSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn):
SELECTOR = getattr(selectors, 'EpollSelector', None) 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'), @unittest.skipUnless(hasattr(selectors, 'KqueueSelector'),
"Test needs selectors.KqueueSelector)") "Test needs selectors.KqueueSelector)")
...@@ -482,6 +493,18 @@ class KqueueSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn): ...@@ -482,6 +493,18 @@ class KqueueSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn):
SELECTOR = getattr(selectors, 'KqueueSelector', None) 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'), @unittest.skipUnless(hasattr(selectors, 'DevpollSelector'),
"Test needs selectors.DevpollSelector") "Test needs selectors.DevpollSelector")
......
...@@ -277,6 +277,9 @@ Library ...@@ -277,6 +277,9 @@ Library
- Issue #28176: Fix callbacks race in asyncio.SelectorLoop.sock_connect. - Issue #28176: Fix callbacks race in asyncio.SelectorLoop.sock_connect.
- Issue #27759: Fix selectors incorrectly retain invalid file descriptors.
Patch by Mark Williams.
IDLE IDLE
---- ----
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment