From 0961dbdea2a449fc5b7d77610d6d10e6036fbdf3 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 3 Apr 2020 14:09:02 +0200 Subject: [PATCH] bpo-40140: test_builtin.PtyTests registers SIGHUP handler (GH-19314) (GH-19316) (GH-19318) test_builtin.PtyTests now registers an handler for SIGHUP signal. Closing the PTY file descriptor can emit a SIGHUP signal: just ignore it. run_child() now also closes the PTY file descriptor before waiting for the process completition, otherwise the test hangs on AIX. (cherry picked from commit 7a51a7e19f0143f75f8fc9ff68f93ed40937aec6) (cherry picked from commit 745bd91bab8e57c52d63a2d541465551d7551f78) --- Lib/test/test_builtin.py | 17 +++++++++++++++++ Lib/test/test_pty.py | 6 +++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index c60560ea6d3..40f83de57d6 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -1639,7 +1639,21 @@ class PtyTests(unittest.TestCase): """Tests that use a pseudo terminal to guarantee stdin and stdout are terminals in the test environment""" + @staticmethod + def handle_sighup(signum, frame): + # bpo-40140: if the process is the session leader, os.close(fd) + # of "pid, fd = pty.fork()" can raise SIGHUP signal: + # just ignore the signal. + pass + def run_child(self, child, terminal_input): + old_sighup = signal.signal(signal.SIGHUP, self.handle_sighup) + try: + return self._run_child(child, terminal_input) + finally: + signal.signal(signal.SIGHUP, old_sighup) + + def _run_child(self, child, terminal_input): r, w = os.pipe() # Pipe test results from child back to parent try: pid, fd = pty.fork() @@ -1690,6 +1704,9 @@ class PtyTests(unittest.TestCase): child_output = child_output.decode("ascii", "ignore") self.fail("got %d lines in pipe but expected 2, child output was:\n%s" % (len(lines), child_output)) + + # bpo-40155: Close the PTY before waiting for the child process + # completion, otherwise the child process hangs on AIX. os.close(fd) # Wait until the child process completes diff --git a/Lib/test/test_pty.py b/Lib/test/test_pty.py index ce85f575a08..dfb3a3fc326 100644 --- a/Lib/test/test_pty.py +++ b/Lib/test/test_pty.py @@ -70,7 +70,7 @@ class PtyTest(unittest.TestCase): self.addCleanup(signal.signal, signal.SIGALRM, old_alarm) old_sighup = signal.signal(signal.SIGHUP, self.handle_sighup) - self.addCleanup(signal.signal, signal.SIGHUP, old_alarm) + self.addCleanup(signal.signal, signal.SIGHUP, old_sighup) # isatty() and close() can hang on some platforms. Set an alarm # before running the test to make sure we don't hang forever. @@ -81,8 +81,8 @@ class PtyTest(unittest.TestCase): self.fail("isatty hung") @staticmethod - def handle_sighup(sig, frame): - # if the process is the session leader, os.close(master_fd) + def handle_sighup(signum, frame): + # bpo-38547: if the process is the session leader, os.close(master_fd) # of "master_fd, slave_name = pty.master_open()" raises SIGHUP # signal: just ignore the signal. pass