]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.13] gh-140482: Avoid changing terminal settings in test_pty (gh-142202) (gh-142238)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Fri, 5 Dec 2025 20:20:42 +0000 (21:20 +0100)
committerGitHub <noreply@github.com>
Fri, 5 Dec 2025 20:20:42 +0000 (15:20 -0500)
The previous test_spawn_doesnt_hang test had a few problems:

* It would cause ENV CHANGED failures if other tests were running
  concurrently due to stty changes
* Typing while the test was running could cause it to fail
(cherry picked from commit c0c65141b37029bfb364094a6dfb4c75ebf8359e)

Co-authored-by: Sam Gross <colesbury@gmail.com>
Lib/test/test_pty.py

index c1728f5019d042659b7055553ac9dd8485c56911..fad34d5cb1c1e86c69f4f10cec86cab1891e0a17 100644 (file)
@@ -3,7 +3,6 @@ from test.support import (
     is_android, is_apple_mobile, is_emscripten, is_wasi, reap_children, verbose
 )
 from test.support.import_helper import import_module
-from test.support.os_helper import TESTFN, unlink
 
 # Skip these tests if termios is not available
 import_module('termios')
@@ -297,26 +296,27 @@ class PtyTest(unittest.TestCase):
         self.assertEqual(data, b"")
 
     def test_spawn_doesnt_hang(self):
-        self.addCleanup(unlink, TESTFN)
-        with open(TESTFN, 'wb') as f:
-            STDOUT_FILENO = 1
-            dup_stdout = os.dup(STDOUT_FILENO)
-            os.dup2(f.fileno(), STDOUT_FILENO)
-            buf = b''
-            def master_read(fd):
-                nonlocal buf
-                data = os.read(fd, 1024)
-                buf += data
-                return data
+        # gh-140482: Do the test in a pty.fork() child to avoid messing
+        # with the interactive test runner's terminal settings.
+        pid, fd = pty.fork()
+        if pid == pty.CHILD:
+            pty.spawn([sys.executable, '-c', 'print("hi there")'])
+            os._exit(0)
+
+        try:
+            buf = bytearray()
             try:
-                pty.spawn([sys.executable, '-c', 'print("hi there")'],
-                          master_read)
-            finally:
-                os.dup2(dup_stdout, STDOUT_FILENO)
-                os.close(dup_stdout)
-        self.assertEqual(buf, b'hi there\r\n')
-        with open(TESTFN, 'rb') as f:
-            self.assertEqual(f.read(), b'hi there\r\n')
+                while (data := os.read(fd, 1024)) != b'':
+                    buf.extend(data)
+            except OSError as e:
+                if e.errno != errno.EIO:
+                    raise
+
+            (pid, status) = os.waitpid(pid, 0)
+            self.assertEqual(status, 0)
+            self.assertEqual(bytes(buf), b"hi there\r\n")
+        finally:
+            os.close(fd)
 
 class SmallPtyTests(unittest.TestCase):
     """These tests don't spawn children or hang."""