Skip to content

Issue with running sudo in subprocess.Popen if /etc/sudoers enables use_pty #139412

@Wenzel

Description

@Wenzel

Bug report

Bug description:

Summary

Terminal output becomes corrupted/shifted when running a subprocess with sudo using subprocess.Popen. This is a regression introduced in Python 3.7 and still present in Python 3.14-rc.

Python Versions Affected

  • Works correctly: Python 3.6.15
  • Broken: Python 3.7.17, Python 3.14-rc (and presumably all versions in between)

Environment

  • OS: Linux (Docker containers)
  • Tested on: python:3.6, python:3.7, python:3.14-rc-bookworm
  • Terminal: Docker TTY
  • Subprocess command: sudo ping 192.0.2.1

Expected Behavior

Terminal output should remain properly formatted, with log messages appearing on their correct line positions (as seen in Python 3.6).

Image

Actual Behavior

Terminal output becomes visually corrupted with text appearing in wrong positions, overwriting previous lines or shifting unexpectedly. Text appears to ignore carriage returns or line positioning, causing output to overlay incorrectly.

Image

Reproduction Code

Dockerfile (adapt FROM line to test different versions):

FROM python:3.14-rc-bookworm
# Also reproducible with: FROM python:3.7

RUN apt-get update && apt-get install -y sudo inetutils-ping
RUN useradd --create-home --uid 1000 --user-group --groups sudo --shell /bin/bash reporter && \
    echo "reporter ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
USER reporter
WORKDIR /home/reporter
COPY --chown=reporter:reporter corruption.py .
ENTRYPOINT [ "python" ]
CMD [ "corruption.py" ]

corruption.py

#!/usr/bin/env python3

import logging
import subprocess
from typing import List
import time
import os


def _build_proc_cmdline() -> List[str]:
    cmd = [
        "sudo",
        "ping",
        "192.0.2.1"
    ]
    return cmd


logging.basicConfig(level=logging.INFO)
logging.info("Current Python version: %s", ".".join(map(str, os.sys.version_info[:3])))
cmd = _build_proc_cmdline()
logging.info("Running command: %s", cmd)
proc = subprocess.Popen(cmd, stdout=None, stderr=None)

for i in range(5):
    time.sleep(1)
    logging.info("Message %s: proc.status = %s", i, proc.poll())
proc.terminate()

Steps to reproduce

Steps to Reproduce

  1. Build Docker image: docker build -t python_corruption .
  2. Run container with TTY: docker run -it python_corruption
  3. Observe corrupted terminal output
  4. Change Dockerfile to FROM python:3.6 and repeat - output is clean

Tested Workarounds

  • Changing stderr parameter: No effect
  • Changing TERM variable: No effect (initially suspected Docker/terminal issue)

CPython versions tested on:

3.14

Operating systems tested on:

Linux

Metadata

Metadata

Assignees

No one assigned

    Labels

    OS-linuxstdlibStandard Library Python modules in the Lib/ directorytopic-subprocessSubprocess issues.type-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions