install: four round-nine review fixes across installer and uninstallers
Ninth review round; each item reproduced before fixing. The inner WSL install ran install.sh without /usr/lib/wsl/lib on PATH, so its GPU detection (which checked PATH and /usr/bin only) could pick CPU torch wheels on the exact Spark/N1X path this PR exists for, failing the later torch.cuda probe. The forwarded env now appends /usr/lib/wsl/lib to PATH (appended, so a PATH nvidia-smi still wins), and install.sh's _has_usable_nvidia_gpu and torch-index _smi resolution gained the same location fallback for direct WSL runs. Three WSL failure paths in install.ps1 (WSL-not-installed deferral, the download sentinel, and the final torch.cuda failure) set LASTEXITCODE and returned, bypassing the round-eight Exit-InstallFailure fix, so powershell -Command automation using the published pipe form still saw success on those failures. All three now route through Exit-InstallFailure, which restores the rolled-aside venv and fails the process in every invocation mode. The uninstall.ps1 WSL cleanup removed /root/.unsloth before killing and matched only full argv, so cmake/nvcc children of a live CUDA build (relative argv after the provisioner cds into the tree) survived the rm and recreated files. The cleanup now signals each matched PID's whole process group (guarded against the shell's own pgid, direct children via pkill -P as fallback) before any rm; the /proc cmdline greps are unaffected by kill order since they read process state, not files. The round-eight same-group fallback called pkill -P without a guard; under this script's set -e a matched provisioner with no children at that instant (TERM pass already reaped them) aborted the whole uninstaller before any cleanup. Now || true, like the kill beside it. Reproduced in a dash sandbox with set -e: a childless matched PID previously killed the harness, now dies cleanly while setsid-group and same-group scenarios keep passing. Verified: bash -n on both shell scripts, sh -n on the extracted WSL clean snippet, PowerShell AST parse on both ps1 files, the three- scenario kill sandbox, gpu-detection and installer-index pytest suites pass, and the sh battery matches the branch baseline.
This commit is contained in:
parent
07ccf2b233
commit
2dc8b99803
4 changed files with 37 additions and 27 deletions
33
install.ps1
33
install.ps1
|
|
@ -2153,13 +2153,10 @@ exit 0
|
|||
substep "in an ADMINISTRATOR PowerShell run: wsl --install" "Cyan"
|
||||
substep "reboot, then re-run: irm https://unsloth.ai/install.ps1 | iex" "Cyan"
|
||||
}
|
||||
# Deferred until reboot: restore any rolled-aside previous venv and signal not-complete.
|
||||
# `exit 1` for -File (plain return exits 0); under `irm | iex` (no $PSCommandPath) return,
|
||||
# since exit would kill the user's shell.
|
||||
Restore-StudioVenvRollback
|
||||
$global:LASTEXITCODE = 1
|
||||
if ($PSCommandPath) { exit 1 }
|
||||
return
|
||||
# Deferred until reboot: signal not-complete through Exit-InstallFailure
|
||||
# (restores the rolled-aside venv, exits 1 for -File, throws under iex so
|
||||
# -Command automation cannot see a deferred setup as success).
|
||||
return (Exit-InstallFailure "WSL setup deferred: enable WSL2 and reboot, then re-run the installer")
|
||||
}
|
||||
|
||||
$distro = if ($env:UNSLOTH_WSL_DISTRO) { $env:UNSLOTH_WSL_DISTRO } else { "Ubuntu-24.04" }
|
||||
|
|
@ -2252,6 +2249,11 @@ exit 0
|
|||
# below requires it, so a run that dies mid-install can no longer coast on
|
||||
# a stale venv passing the torch/CLI probes.
|
||||
$_fwdEnv += 'export UNSLOTH_SKIP_WSL_WINDOWS_SHORTCUT=1; mkdir -p /root/.unsloth; touch /root/.unsloth/.skip-wsl-windows-shortcut; rm -f /root/.unsloth/.install-ok; '
|
||||
# Root login shells reset PATH via /etc/profile and can drop /usr/lib/wsl/lib,
|
||||
# the only nvidia-smi location under WSL2 GPU-PV; without it install.sh's GPU
|
||||
# detection picks CPU torch wheels and the torch.cuda probe then fails the
|
||||
# whole install. Appended (not prepended) so a PATH nvidia-smi still wins.
|
||||
$_fwdEnv += 'export PATH="$PATH:/usr/lib/wsl/lib"; '
|
||||
# Forward a non-default --package into the WSL install (already validated
|
||||
# against ^[a-zA-Z0-9][a-zA-Z0-9._-]*$ at parse time, so splicing is safe);
|
||||
# previously it was silently dropped and the user got stock unsloth.
|
||||
|
|
@ -2284,10 +2286,9 @@ exit 0
|
|||
# probes below would only re-validate a stale venv from a previous install.
|
||||
if ($wslRc -eq 86) {
|
||||
step "wsl" "could not download install.sh inside WSL (network or bad ref) -- the installer never ran." "Yellow"
|
||||
Restore-StudioVenvRollback
|
||||
$global:LASTEXITCODE = 1
|
||||
if ($PSCommandPath) { exit 1 }
|
||||
return
|
||||
# Exit-InstallFailure restores the rollback and fails the process in every
|
||||
# invocation mode (exit for -File, throw for iex/-Command automation).
|
||||
return (Exit-InstallFailure "could not download install.sh inside WSL; the installer never ran")
|
||||
}
|
||||
# $wslRc can be non-zero from the llama.cpp prebuilt step even on success, so verify torch.cuda directly.
|
||||
$torchOk = $false
|
||||
|
|
@ -2541,12 +2542,10 @@ exit 0
|
|||
$global:LASTEXITCODE = 0
|
||||
return
|
||||
}
|
||||
# Failed (torch.cuda unavailable): restore any rolled-aside previous venv and report non-zero
|
||||
# (plain return exits 0 for -File; under iex `exit` would kill the caller's shell).
|
||||
Restore-StudioVenvRollback
|
||||
$global:LASTEXITCODE = 1
|
||||
if ($PSCommandPath) { exit 1 }
|
||||
return
|
||||
# Failed (torch.cuda unavailable): Exit-InstallFailure restores the rolled-aside
|
||||
# venv and fails the process in every invocation mode, so iex/-Command
|
||||
# automation cannot read this as success.
|
||||
return (Exit-InstallFailure "WSL Studio install did not finish cleanly (torch.cuda not detected; inner exit $wslRc)")
|
||||
}
|
||||
|
||||
# ── GPU arch → newest compatible Windows ROCm wheel release ──
|
||||
|
|
|
|||
|
|
@ -1554,6 +1554,11 @@ _has_usable_nvidia_gpu() {
|
|||
_nvsmi=""
|
||||
if command -v nvidia-smi >/dev/null 2>&1; then
|
||||
_nvsmi="nvidia-smi"
|
||||
elif [ -x "/usr/lib/wsl/lib/nvidia-smi" ]; then
|
||||
# WSL2 GPU-PV ships nvidia-smi ONLY here, and root login shells drop
|
||||
# the dir from PATH; without this fallback the WSL install detects no
|
||||
# NVIDIA GPU and picks CPU torch wheels.
|
||||
_nvsmi="/usr/lib/wsl/lib/nvidia-smi"
|
||||
elif [ -x "/usr/bin/nvidia-smi" ]; then
|
||||
_nvsmi="/usr/bin/nvidia-smi"
|
||||
fi
|
||||
|
|
@ -2074,6 +2079,9 @@ get_torch_index_url() {
|
|||
_nvidia_detected=1
|
||||
if command -v nvidia-smi >/dev/null 2>&1; then
|
||||
_smi="nvidia-smi"
|
||||
elif [ -x "/usr/lib/wsl/lib/nvidia-smi" ]; then
|
||||
# Same WSL2 GPU-PV location fallback as _has_usable_nvidia_gpu.
|
||||
_smi="/usr/lib/wsl/lib/nvidia-smi"
|
||||
elif [ -x "/usr/bin/nvidia-smi" ]; then
|
||||
_smi="/usr/bin/nvidia-smi"
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -605,15 +605,18 @@ function Uninstall-UnslothStudio {
|
|||
if (Get-Command wsl.exe -ErrorAction SilentlyContinue) {
|
||||
try {
|
||||
# Probe candidates by exit code ('' = default distro) since `wsl --list` emits UTF-16 PS
|
||||
# mis-parses. rm runs FIRST (the kills could SIGKILL this shell) and drops the dangling
|
||||
# /root/.local/bin/unsloth symlink. Scope STRICTLY to /root (the fallback's install dir);
|
||||
# /home/*/.unsloth may be another user's. The 8888 kill only targets a listener whose
|
||||
# process cmdline is under /root/.unsloth (Studio's bind), so an unrelated service on 8888
|
||||
# -- Jupyter et al. default to it -- is NOT killed; it's also gated on an Unsloth install
|
||||
# having existed (checked BEFORE rm deletes the marker). pkill matches argv containing
|
||||
# /root/.unsloth/ (not bare names that would hit a user's own llama-server); the backslash
|
||||
# + [h]-bracket in '/root/\.unslot[h]/' keep it from matching this command's own argv.
|
||||
$_clean = '_had=0; if [ -d /root/.unsloth ] || [ -L /root/.local/bin/unsloth ]; then _had=1; fi; rm -rf /root/.unsloth /root/llama-cuda /root/provision_llama_cuda.sh /root/llama_cuda_build.log 2>/dev/null; rm -f /root/.local/bin/unsloth 2>/dev/null; if [ $_had -eq 1 ]; then for _p in $(fuser 8888/tcp 2>/dev/null); do grep -qa /root/\.unsloth/ /proc/$_p/cmdline 2>/dev/null && kill -9 $_p 2>/dev/null; done; fi; pkill -9 -f ''/root/\.unslot[h]/'' 2>/dev/null; true'
|
||||
# mis-parses. Kills run BEFORE rm: a live CUDA build (cmake/nvcc under
|
||||
# /root/.unsloth/llama.cpp) would otherwise keep burning CPU/GPU and recreate files after
|
||||
# the rm. Each matched PID's whole process GROUP is signalled (cmake --build children carry
|
||||
# relative argv no pattern can match), guarded against this shell's own pgid, plus direct
|
||||
# children via pkill -P; this shell cannot self-match (its argv carries an extra backslash
|
||||
# and the [h]-bracket in the pkill pattern). Scope STRICTLY to /root (the fallback's
|
||||
# install dir); /home/*/.unsloth may be another user's. The 8888 kill only targets a
|
||||
# listener whose process cmdline is under /root/.unsloth (Studio's bind), so an unrelated
|
||||
# service on 8888 -- Jupyter et al. default to it -- is NOT killed; it's also gated on an
|
||||
# Unsloth install having existed. /proc cmdline greps still work after kills since they
|
||||
# read process state, not files.
|
||||
$_clean = '_had=0; if [ -d /root/.unsloth ] || [ -L /root/.local/bin/unsloth ]; then _had=1; fi; _mypg=$(ps -o pgid= -p $$ 2>/dev/null | tr -d " "); for _p in $(pgrep -f ''/root/\.unslot[h]/'' 2>/dev/null); do _pg=$(ps -o pgid= -p $_p 2>/dev/null | tr -d " "); case "$_pg" in ""|0|1|"$_mypg") pkill -9 -P $_p 2>/dev/null; kill -9 $_p 2>/dev/null ;; *) kill -9 -- -$_pg 2>/dev/null || kill -9 $_p 2>/dev/null ;; esac; done; if [ $_had -eq 1 ]; then for _p in $(fuser 8888/tcp 2>/dev/null); do grep -qa /root/\.unsloth/ /proc/$_p/cmdline 2>/dev/null && kill -9 $_p 2>/dev/null; done; fi; rm -rf /root/.unsloth /root/llama-cuda /root/provision_llama_cuda.sh /root/llama_cuda_build.log 2>/dev/null; rm -f /root/.local/bin/unsloth 2>/dev/null; true'
|
||||
# Clean only distros with evidence of a fallback install: the wsl-distro.txt marker or an
|
||||
# explicit UNSLOTH_WSL_DISTRO. The broad candidate probe is only for legacy marker-less
|
||||
# installs (ARM64 only); on x86 it would delete distros this installer never touched
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ if command -v pkill >/dev/null 2>&1; then
|
|||
_pgid=$(ps -o pgid= -p "$_pid" 2>/dev/null | tr -d '[:space:]')
|
||||
case "$_pgid" in
|
||||
''|0|1|"$_self_pgid")
|
||||
pkill "-$_sig" -P "$_pid" 2>/dev/null
|
||||
pkill "-$_sig" -P "$_pid" 2>/dev/null || true
|
||||
kill -s "$_sig" "$_pid" 2>/dev/null || true ;;
|
||||
*) kill -s "$_sig" -- "-$_pgid" 2>/dev/null \
|
||||
|| kill -s "$_sig" "$_pid" 2>/dev/null || true ;;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue