[3.14] gh-140482: Avoid changing terminal settings in test_pty (gh-142202) (gh-142239)

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 c0c65141b3)

Co-authored-by: Sam Gross <colesbury@gmail.com>
This commit is contained in:
Miss Islington (bot) 2025-12-05 17:18:40 +01:00 committed by GitHub
parent 7eec794f1a
commit 8fd39c0e51
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

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