# HG changeset patch # Parent 19488e23dcdb74faab92eaf46a2d642dd85be8ef Issue #23680: Resend signals with setitimer() in case Python wasn’t ready Also, close the pipe to avoid the need for a one second timeout. diff -r 19488e23dcdb Lib/test/test_io.py --- a/Lib/test/test_io.py Fri Jun 03 10:48:43 2016 +0300 +++ b/Lib/test/test_io.py Fri Jun 03 13:38:43 2016 +0000 @@ -3814,26 +3814,24 @@ """Check that a buffered write, when it gets interrupted (either returning a partial result or EINTR), properly invokes the signal handler and retries if the latter returned successfully.""" - select = support.import_module("select") # A quantity that exceeds the buffer size of an anonymous pipe's # write end. N = support.PIPE_MAX_SIZE r, w = os.pipe() - fdopen_kwargs["closefd"] = False # We need a separate thread to read from the pipe and allow the # write() to finish. This thread is started after the SIGALRM is # received (forcing a first EINTR in write()). read_results = [] - write_finished = False error = None def _read(): try: - while not write_finished: - while r in select.select([r], [], [], 1.0)[0]: - s = os.read(r, 1024) - read_results.append(s) + while True: + s = os.read(r, 1024) + if not s: + break + read_results.append(s) except BaseException as exc: nonlocal error error = exc @@ -3841,15 +3839,15 @@ t.daemon = True def alarm1(sig, frame): signal.signal(signal.SIGALRM, alarm2) - signal.alarm(1) def alarm2(sig, frame): + signal.setitimer(signal.ITIMER_REAL, 0) t.start() large_data = item * N signal.signal(signal.SIGALRM, alarm1) try: wio = self.io.open(w, **fdopen_kwargs) - signal.alarm(1) + signal.setitimer(signal.ITIMER_REAL, 0.1, 0.1) # Expected behaviour: # - first raw write() is partial (because of the limited pipe buffer # and the first alarm) @@ -3858,24 +3856,15 @@ written = wio.write(large_data) self.assertEqual(N, written) - wio.flush() - write_finished = True + wio.close() t.join() self.assertIsNone(error) self.assertEqual(N, sum(len(x) for x in read_results)) finally: - write_finished = True - os.close(w) + signal.setitimer(signal.ITIMER_REAL, 0) os.close(r) - # This is deliberate. If we didn't close the file descriptor - # before closing wio, wio would try to flush its internal - # buffer, and could block (in case of failure). - try: - wio.close() - except OSError as e: - if e.errno != errno.EBADF: - raise + wio.close() def test_interrupted_write_retry_buffered(self): self.check_interrupted_write_retry(b"x", mode="wb")