Skip to content

Backport gh-144248 to 3.14: pyrepl on Windows loops forever printing tracebacks when stdin is the NUL device #161623

Closed as duplicate

Description

@mishulantis

Bug report

Bug description:

On Windows with Python 3.14.x, starting the REPL with the NUL device as stdin and a pipe as stdout makes _pyrepl print the same traceback in an endless loop. The output never stops. In one real incident, an unattended process wrote 5.38 GB of identical tracebacks to a log file over about 26 minutes before it was killed.

This is easy to trigger by accident. In Git Bash (MSYS), both an empty heredoc and </dev/null give the child process the Windows NUL device as stdin, and os.isatty() returns True for it. So the isatty check in _pyrepl/main.py passes and pyrepl is chosen.

Reproduction (Git Bash on Windows 11, python.org 3.14.3):

$ timeout 3 python - <<'EOF' 2>&1 | wc -c
EOF
14266063

That is about 14 MB in 3 seconds. Every iteration prints:

Traceback (most recent call last):
  File "...\Lib\_pyrepl\readline.py", line 395, in multiline_input
    return reader.readline()
  File "...\Lib\_pyrepl\reader.py", line 752, in readline
    self.prepare()
  File "...\Lib\_pyrepl\historical_reader.py", line 306, in prepare
    super().prepare()
  File "...\Lib\_pyrepl\reader.py", line 585, in prepare
    self.console.prepare()
  File "...\Lib\_pyrepl\windows_console.py", line 359, in prepare
    self.height, self.width = self.getheightwidth()
  File "...\Lib\_pyrepl\windows_console.py", line 410, in getheightwidth
    raise WinError(GetLastError())
OSError: [WinError 123] <localized: The filename, directory name, or volume label syntax is incorrect.>

The error code is stale. That matches gh-132888, where ctypes.GetLastError() was used incorrectly. Because the console error is not caught at init time, pyrepl gets as far as the interactive loop. There, the bare except: in run_multiline_interactive_console (simple_interact.py) shows the traceback and retries, so the persistent error turns into an infinite loop.

Comparison (same machine, same command):

  • printf '' | python - exits 0 with no output (real empty pipe, not a tty).
  • PYTHON_BASIC_REPL=1 python - <<'EOF' / EOF prints the banner and >>> , then exits 0.

Status on branches:

Request:

  1. Please backport gh-132888: Fix Windows API error checking in pyrepl.windows_console #144248 (or an equivalent fix) to 3.14.
  2. Separately, consider bounding the retry loop in run_multiline_interactive_console. A console error that happens on every iteration should abort, or fall back to the basic REPL, instead of retrying forever.

I have not built main to confirm that this exact case (stdin = NUL, stdout = pipe) falls back correctly there.

CPython versions tested on:

3.14

Operating systems tested on:

Windows

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions