Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions tests/tools/test_find_shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,32 @@ def fake_run(argv, **kwargs):
assert local_mod._bash_starts(r"C:\Git\bin\bash.exe") is True
assert calls[0][0][-1] == "/usr/bin/true; /usr/bin/cat --version >/dev/null"

def test_probe_never_inherits_host_stdin(self, monkeypatch):
"""The probe must not inherit fd 0 (#73693).

Under a JSON-RPC stdio host — ACP, or the TUI gateway of #14036 —
stdin is the protocol pipe. MSYS bash blocks on it at startup, and
the probe's own timeout only reaps the Git wrapper process, so the
surviving mingw child holds the pipe and hangs the turn.
"""
import tools.environments.local as local_mod

local_mod._bash_starts_cache.clear()
local_mod._bash_probe_details_cache.clear()
calls = []

def fake_run(argv, **kwargs):
calls.append(kwargs)
return subprocess.CompletedProcess(argv, 0, stdout="", stderr="")

monkeypatch.setattr(local_mod.subprocess, "run", fake_run)
monkeypatch.setattr(local_mod, "_IS_WINDOWS", True)

local_mod._bash_starts(r"C:\Git\bin\bash.exe")

assert calls, "expected the probe to spawn bash"
assert calls[0].get("stdin") is subprocess.DEVNULL

def test_aslr_failure_surfaces_targeted_windows_command(
self, tmp_path, monkeypatch
):
Expand Down
7 changes: 7 additions & 0 deletions tools/environments/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -845,6 +845,7 @@ def _mandatory_aslr_enabled() -> "bool | None":
"(Get-ProcessMitigation -System).Aslr.ForceRelocateImages.ToString()",
],
capture_output=True,
stdin=subprocess.DEVNULL,
text=True, encoding="utf-8", errors="replace",
timeout=10,
creationflags=windows_hide_flags(),
Expand Down Expand Up @@ -911,6 +912,12 @@ def _bash_starts(bash: str) -> bool:
result = subprocess.run(
[bash, "--noprofile", "--norc", "-c", _BASH_EXTERNAL_PROGRAM_PROBE],
capture_output=True,
# Never let the probe inherit the host's stdin. Under a JSON-RPC
# stdio host (ACP/TUI gateway) fd 0 is the protocol pipe; MSYS
# bash blocks on it at startup, and the timeout below then kills
# only the Git\bin wrapper — the surviving mingw child keeps the
# pipe open and communicate() hangs the turn. See #73693.
stdin=subprocess.DEVNULL,
text=True, encoding="utf-8", errors="replace",
timeout=15,
creationflags=windows_hide_flags() if _IS_WINDOWS else 0,
Expand Down
Loading