This patch comes from upstream: http://bugs.python.org/issue26228 It has not yet been committed, but seems on track to be, and we need it to fix a bug. --- Python-3.9.0/Lib/pty.py +++ Python-3.9.0/Lib/pty.py @@ -138,7 +138,7 @@ def _copy(master_fd, master_read=_read, if master_fd in rfds: data = master_read(master_fd) if not data: # Reached EOF. - fds.remove(master_fd) + return else: os.write(STDOUT_FILENO, data) if STDIN_FILENO in rfds: @@ -155,7 +155,15 @@ def spawn(argv, master_read=_read, stdin sys.audit('pty.spawn', argv) pid, master_fd = fork() if pid == CHILD: - os.execlp(argv[0], *argv) + try: + os.execlp(argv[0], *argv) + except: + # If we wanted to be really clever, we would use + # the same method as subprocess() to pass the error + # back to the parent. For now just dump stack trace. + traceback.print_exc() + finally: + os._exit(1) try: mode = tty.tcgetattr(STDIN_FILENO) tty.setraw(STDIN_FILENO) @@ -165,6 +173,10 @@ def spawn(argv, master_read=_read, stdin try: _copy(master_fd, master_read, stdin_read) except OSError: + # Some OSes never return an EOF on pty, just raise + # an error instead. + pass + finally: if restore: tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode) --- Python-3.9.0/Lib/test/test_pty.py +++ Python-3.9.0/Lib/test/test_pty.py @@ -306,7 +306,7 @@ class SmallPtyTests(unittest.TestCase): socketpair[1].close() os.close(write_to_stdin_fd) - # Expect two select calls, the last one will cause IndexError + # Expect two select calls, then a normal return on master EOF pty.select = self._mock_select self.select_rfds_lengths.append(2) self.select_rfds_results.append([mock_stdin_fd, masters[0]]) @@ -314,8 +314,7 @@ class SmallPtyTests(unittest.TestCase): # both encountered an EOF before the second select call. self.select_rfds_lengths.append(0) - with self.assertRaises(IndexError): - pty._copy(masters[0]) + pty._copy(masters[0]) def tearDownModule():