Issue #23485: Enhance and update selectors doc and test_selectors
Selector.select() is now retried with the recomputed timeout when interrupted by a signal. Write an unit test with a signal handler raising an exception, and a unit with a signal handler which does not raise an exception (it does nothing).
This commit is contained in:
parent
45ca48b03d
commit
b310173319
|
@ -159,6 +159,12 @@ below:
|
|||
timeout has elapsed if the current process receives a signal: in this
|
||||
case, an empty list will be returned.
|
||||
|
||||
.. versionchanged:: 3.5
|
||||
The selector is now retried with a recomputed timeout when interrupted
|
||||
by a signal if the signal handler did not raise an exception (see
|
||||
:pep:`475` for the rationale), instead of returning an empty list
|
||||
of events before the timeout.
|
||||
|
||||
.. method:: close()
|
||||
|
||||
Close the selector.
|
||||
|
|
|
@ -357,7 +357,35 @@ class BaseSelectorTestCase(unittest.TestCase):
|
|||
|
||||
@unittest.skipUnless(hasattr(signal, "alarm"),
|
||||
"signal.alarm() required for this test")
|
||||
def test_select_interrupt(self):
|
||||
def test_select_interrupt_exc(self):
|
||||
s = self.SELECTOR()
|
||||
self.addCleanup(s.close)
|
||||
|
||||
rd, wr = self.make_socketpair()
|
||||
|
||||
class InterruptSelect(Exception):
|
||||
pass
|
||||
|
||||
def handler(*args):
|
||||
raise InterruptSelect
|
||||
|
||||
orig_alrm_handler = signal.signal(signal.SIGALRM, handler)
|
||||
self.addCleanup(signal.signal, signal.SIGALRM, orig_alrm_handler)
|
||||
self.addCleanup(signal.alarm, 0)
|
||||
|
||||
signal.alarm(1)
|
||||
|
||||
s.register(rd, selectors.EVENT_READ)
|
||||
t = time()
|
||||
# select() is interrupted by a signal which raises an exception
|
||||
with self.assertRaises(InterruptSelect):
|
||||
s.select(30)
|
||||
# select() was interrupted before the timeout of 30 seconds
|
||||
self.assertLess(time() - t, 5.0)
|
||||
|
||||
@unittest.skipUnless(hasattr(signal, "alarm"),
|
||||
"signal.alarm() required for this test")
|
||||
def test_select_interrupt_noraise(self):
|
||||
s = self.SELECTOR()
|
||||
self.addCleanup(s.close)
|
||||
|
||||
|
@ -371,8 +399,11 @@ class BaseSelectorTestCase(unittest.TestCase):
|
|||
|
||||
s.register(rd, selectors.EVENT_READ)
|
||||
t = time()
|
||||
self.assertFalse(s.select(2))
|
||||
self.assertLess(time() - t, 2.5)
|
||||
# select() is interrupted by a signal, but the signal handler doesn't
|
||||
# raise an exception, so select() should by retries with a recomputed
|
||||
# timeout
|
||||
self.assertFalse(s.select(1.5))
|
||||
self.assertGreaterEqual(time() - t, 1.0)
|
||||
|
||||
|
||||
class ScalableSelectorMixIn:
|
||||
|
|
Loading…
Reference in New Issue