Issue #27759: Fix selectors incorrectly retain invalid file descriptors.
Patch by Mark Williams.
This commit is contained in:
parent
d6c6771fc9
commit
525aedc5fa
|
@ -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):
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Reference in New Issue