Skip to content

Commit ba1bcff

Browse files
authored
bpo-29255: Wait in KqueueSelector.select when no fds are registered (GH-19508)
Also partially fixes bpo-25680 (there's still a discrepancy in behavior on Windows that needs to be fixed).
1 parent 4b4e90a commit ba1bcff

File tree

3 files changed

+18
-1
lines changed

3 files changed

+18
-1
lines changed

Lib/selectors.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,10 @@ def unregister(self, fileobj):
552552

553553
def select(self, timeout=None):
554554
timeout = None if timeout is None else max(timeout, 0)
555-
max_ev = len(self._fd_to_key)
555+
# If max_ev is 0, kqueue will ignore the timeout. For consistent
556+
# behavior with the other selector classes, we prevent that here
557+
# (using max). See https://bugs.python.org/issue29255
558+
max_ev = max(len(self._fd_to_key), 1)
556559
ready = []
557560
try:
558561
kev_list = self._selector.control(None, max_ev, timeout)

Lib/test/test_selectors.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,19 @@ def test_register_bad_fd(self):
543543
with self.assertRaises(KeyError):
544544
s.get_key(bad_f)
545545

546+
def test_empty_select_timeout(self):
547+
# Issues #23009, #29255: Make sure timeout is applied when no fds
548+
# are registered.
549+
s = self.SELECTOR()
550+
self.addCleanup(s.close)
551+
552+
t0 = time()
553+
self.assertEqual(s.select(1), [])
554+
t1 = time()
555+
dt = t1 - t0
556+
# Tolerate 2.0 seconds for very slow buildbots
557+
self.assertTrue(0.8 <= dt <= 2.0, dt)
558+
546559

547560
@unittest.skipUnless(hasattr(selectors, 'DevpollSelector'),
548561
"Test needs selectors.DevpollSelector")
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Wait in `KqueueSelector.select` when no fds are registered

0 commit comments

Comments
 (0)