From d9257c8554c5a32874cd769ae40b2f570292ee96 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 2 Apr 2020 21:54:19 +0200 Subject: [PATCH] bpo-31160: Fix test_builtin.test_input_no_stdout_fileno() bpo-31160, bpo-40140, bpo-40155: Fix test_input_no_stdout_fileno() of test_builtin. test.support.wait_process() can now be called with exitcode=None to not check the exit code. Moreover, it now returns the child process exit code, so it can be checked in the caller. --- Doc/library/test.rst | 5 ++++- Lib/test/support/__init__.py | 16 +++++++++++----- Lib/test/test_builtin.py | 12 +++++++----- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/Doc/library/test.rst b/Doc/library/test.rst index c33465d758d574..5f7e7b715fc921 100644 --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -831,12 +831,15 @@ The :mod:`test.support` module defines the following functions: *exitcode*. Raise an :exc:`AssertionError` if the process exit code is not equal to - *exitcode*. + *exitcode*. Use ``exitcode=None`` to not check the process exit code. The + returned process exit code can be used to check it in the caller. If the process runs longer than *timeout* seconds (:data:`SHORT_TIMEOUT` by default), kill the process and raise an :exc:`AssertionError`. The timeout feature is not available on Windows. + Return the process exit code. + .. versionadded:: 3.9 diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 1f792d8514da0f..86c14187c3447d 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -3407,11 +3407,15 @@ def wait_process(pid, *, exitcode, timeout=None): Wait until process pid completes and check that the process exit code is exitcode. - Raise an AssertionError if the process exit code is not equal to exitcode. + Raise an AssertionError if the process exit code is not equal to + exitcode. Use exitcode=None to not check the process exit code. The + returned process exit code can be used to check it in the caller. - If the process runs longer than timeout seconds (SHORT_TIMEOUT by default), - kill the process (if signal.SIGKILL is available) and raise an - AssertionError. The timeout feature is not available on Windows. + If the process runs longer than *timeout* seconds (SHORT_TIMEOUT by + default), kill the process and raise an AssertionError. The timeout feature + is not available on Windows. + + Return the process exit code. """ if os.name != "nt": import signal @@ -3447,10 +3451,12 @@ def wait_process(pid, *, exitcode, timeout=None): pid2, status = os.waitpid(pid, 0) exitcode2 = os.waitstatus_to_exitcode(status) - if exitcode2 != exitcode: + if exitcode is not None and exitcode2 != exitcode: raise AssertionError(f"process {pid} exited with code {exitcode2}, " f"but exit code {exitcode} is expected") # sanity check: it should not fail in practice if pid2 != pid: raise AssertionError(f"pid {pid2} != pid {pid}") + + return exitcode2 diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index eaada1b50439be..d15071c98d3d41 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -1893,13 +1893,15 @@ def run_child(self, child, terminal_input): self.fail("got %d lines in pipe but expected 2, child output was:\n%s" % (len(lines), child_output)) - # Wait until the child process completes before closing the PTY to - # prevent sending SIGHUP to the child process. - support.wait_process(pid, exitcode=0) - - # Close the PTY + # bpo-40140, bpo-40155: Close the PTY before waiting for the child + # process completion, otherwise the child process blocks on AIX + # and Solaris. os.close(fd) + # The child process can be terminated by SIGHUP when the PTY is closed + exitcode = support.wait_process(pid, exitcode=None) + self.assertIn(exitcode, (0, -signal.SIGHUP)) + return lines def check_input_tty(self, prompt, terminal_input, stdio_encoding=None):