Skip to content

fix(trainer): resolve LocalProcessBackend Windows compatibility issues - #762

Open
kingabdulsalamsas111-lgtm wants to merge 1 commit into
kubeflow:mainfrom
kingabdulsalamsas111-lgtm:fix-localprocess-bash-resolution
Open

kingabdulsalamsas111-lgtm wants to merge 1 commit into
kubeflow:mainfrom
kingabdulsalamsas111-lgtm:fix-localprocess-bash-resolution

Conversation

@kingabdulsalamsas111-lgtm

Copy link
Copy Markdown
Contributor

What this PR does / why we need it:

Resolves both issues discussed in #757:

  1. Bash resolution — LocalProcessBackend called subprocess.Popen with the bare string "bash", which on Windows could resolve to a broken WSL relay launcher instead of a working Git Bash install. Now validates that the resolved bash actually runs before using it.

  2. Environment wiping — LocalJob called subprocess.Popen(..., env=self.env) with an explicit env dict. On Windows, passing any explicit env= replaces the entire parent environment instead of extending it, wiping PATH for the training subprocess regardless of the user's system PATH. Now merges self.env into os.environ.

While verifying these two fixes end-to-end on Windows, I also had to fix two supporting issues that were blocking the training subprocess from starting at all:

  1. Path normalization — Windows paths (venv_dir, python_bin) use backslashes, which bash interprets as escape characters, corrupting paths inside the generated bash script. Now normalized to forward slashes.

  2. Scripts/ vs bin/ — Python's venv module creates a Scripts/ folder on Windows, not bin/ (the Unix convention the code assumed). The activate script and binary paths now detect this dynamically.

Verification:

I tested this locally on Windows with LocalProcessBackend + the torch-distributed runtime, before and after the fix:

  • Before: the job crashed immediately with a misleading, unrelated error (RPC call... handle differs...) caused by bash resolving to a broken WSL relay.
  • After: I confirmed the backend successfully resolves a working bash, creates and activates the venv, and installs dependencies (torch, torchvision) end-to-end via pip — verified across multiple runs with full logs.

Which issue(s) this PR fixes (optional, in Fixes #<issue number>, #<issue number>, ... format, will close the issue(s) when PR gets merged):

Fixes #757

Checklist:

  • Docs included if any changes are user facing

- Validate bash resolves to a working executable instead of relying
  on unqualified PATH lookup, which could pick a broken WSL relay
  over a working Git Bash install (fixes kubeflow#757)
- Fix subprocess.Popen env= replacing the entire parent environment
  on Windows instead of extending it, which wiped PATH for the
  training subprocess
- Normalize backslash paths (venv_dir, python_bin) to forward
  slashes, required by bash script templates
- Detect Scripts/ vs bin/ venv layout dynamically, since Windows
  venvs use Scripts/ rather than the Unix bin/ convention

Signed-off-by: kingabdulsalamsas111-lgtm <kingabdulsalamsas111@gmail.com>
@google-oss-prow

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign astefanutti for approval. For more information see the Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kingabdulsalamsas111-lgtm

Copy link
Copy Markdown
Contributor Author

@robert-bell @andreyvelich PR #762 is ready for review, with all Windows LocalProcessBackend issues fixed and verified end-to-end.

@aniket-3001 aniket-3001 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

repro'd #757 on win11 (git bash + wsl): which("bash") gives git bash but subprocess launches the wsl one, main fails with [WinError 87]. that's the empty env={}, the env merge in job.py fixes it, nice.

tried it on linux too (python:3.11 container), 3 things inline. unit tests pass there since they mock the script, so CI won't catch these. maybe a test for the generated script on both nt and posix?

unrelated, hit it while testing: python/temp path with a space breaks the script, vars aren't quoted (C:/Users/Aniket: No such file or directory). quoting got me further but the torchrun line and cleanup need it too, so separate issue? can open one

$PYENV_LOCATION/bin/python -m ensurepip --upgrade --default-pip
if [ -d "$PYENV_LOCATION/Scripts" ]; then VENV_BIN="$PYENV_LOCATION/Scripts"; else VENV_BIN="$PYENV_LOCATION/bin"; fi
source $VENV_BIN/activate
$VENV_BIN/python.exe -m ensurepip --upgrade --default-pip

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this runs on every OS but linux/mac venvs only have bin/python, no python.exe. job now dies here (bin/python.exe: No such file or directory), on main it gets through ensurepip. maybe a VENV_PYTHON next to VENV_BIN?

_c = [os.path.join(venv_bin_dir, local_exec_constants.TORCH_COMMAND)]
trainer.set_command(tuple(_c))
torch_command = str(
Path(venv_bin_dir) / f"{local_exec_constants.TORCH_COMMAND}.exe"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same on linux, script ends up calling bin/torchrun.exe. the Scripts vs bin bit above checks os.name, this probably needs it too

return t.substitute(**mapping)


def _resolve_bash() -> str:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tried a healthy wsl: bash --version returns 0 so if System32�ash.exe is before git on PATH it gets picked. job then runs in wsl and fails on the windows paths (/bin/bash: C:/Users/...: No such file or directory). so broken wsl is fixed, working wsl ahead of git isn't. prefer the git paths first, or check uname -s?

This branch has not been deployed

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

LocalProcessBackend crashes on Windows due to bash PATH resolution conflict (WSL relay vs Git Bash)

2 participants