Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 525aedc

Browse files
committed
Issue #27759: Fix selectors incorrectly retain invalid file descriptors.
Patch by Mark Williams.
1 parent d6c6771 commit 525aedc

3 files changed

Lines changed: 43 additions & 9 deletions

File tree

Lib/selectors.py

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,11 @@ def register(self, fileobj, events, data=None):
408408
epoll_events |= select.EPOLLIN
409409
if events & EVENT_WRITE:
410410
epoll_events |= select.EPOLLOUT
411-
self._epoll.register(key.fd, epoll_events)
411+
try:
412+
self._epoll.register(key.fd, epoll_events)
413+
except BaseException:
414+
super().unregister(fileobj)
415+
raise
412416
return key
413417

414418
def unregister(self, fileobj):
@@ -530,14 +534,18 @@ def fileno(self):
530534

531535
def register(self, fileobj, events, data=None):
532536
key = super().register(fileobj, events, data)
533-
if events & EVENT_READ:
534-
kev = select.kevent(key.fd, select.KQ_FILTER_READ,
535-
select.KQ_EV_ADD)
536-
self._kqueue.control([kev], 0, 0)
537-
if events & EVENT_WRITE:
538-
kev = select.kevent(key.fd, select.KQ_FILTER_WRITE,
539-
select.KQ_EV_ADD)
540-
self._kqueue.control([kev], 0, 0)
537+
try:
538+
if events & EVENT_READ:
539+
kev = select.kevent(key.fd, select.KQ_FILTER_READ,
540+
select.KQ_EV_ADD)
541+
self._kqueue.control([kev], 0, 0)
542+
if events & EVENT_WRITE:
543+
kev = select.kevent(key.fd, select.KQ_FILTER_WRITE,
544+
select.KQ_EV_ADD)
545+
self._kqueue.control([kev], 0, 0)
546+
except BaseException:
547+
super().unregister(fileobj)
548+
raise
541549
return key
542550

543551
def unregister(self, fileobj):

Lib/test/test_selectors.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from time import sleep
1010
import unittest
1111
import unittest.mock
12+
import tempfile
1213
from time import monotonic as time
1314
try:
1415
import resource
@@ -475,13 +476,35 @@ class EpollSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn):
475476

476477
SELECTOR = getattr(selectors, 'EpollSelector', None)
477478

479+
def test_register_file(self):
480+
# epoll(7) returns EPERM when given a file to watch
481+
s = self.SELECTOR()
482+
with tempfile.NamedTemporaryFile() as f:
483+
with self.assertRaises(IOError):
484+
s.register(f, selectors.EVENT_READ)
485+
# the SelectorKey has been removed
486+
with self.assertRaises(KeyError):
487+
s.get_key(f)
488+
478489

479490
@unittest.skipUnless(hasattr(selectors, 'KqueueSelector'),
480491
"Test needs selectors.KqueueSelector)")
481492
class KqueueSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn):
482493

483494
SELECTOR = getattr(selectors, 'KqueueSelector', None)
484495

496+
def test_register_bad_fd(self):
497+
# a file descriptor that's been closed should raise an OSError
498+
# with EBADF
499+
s = self.SELECTOR()
500+
bad_f = support.make_bad_fd()
501+
with self.assertRaises(OSError) as cm:
502+
s.register(bad_f, selectors.EVENT_READ)
503+
self.assertEqual(cm.exception.errno, errno.EBADF)
504+
# the SelectorKey has been removed
505+
with self.assertRaises(KeyError):
506+
s.get_key(bad_f)
507+
485508

486509
@unittest.skipUnless(hasattr(selectors, 'DevpollSelector'),
487510
"Test needs selectors.DevpollSelector")

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,9 @@ Library
277277

278278
- Issue #28176: Fix callbacks race in asyncio.SelectorLoop.sock_connect.
279279

280+
- Issue #27759: Fix selectors incorrectly retain invalid file descriptors.
281+
Patch by Mark Williams.
282+
280283
IDLE
281284
----
282285

0 commit comments

Comments
 (0)