diff --git a/scripts/uninstall.ps1 b/scripts/uninstall.ps1 index 020fb85781..34e60fbc93 100644 --- a/scripts/uninstall.ps1 +++ b/scripts/uninstall.ps1 @@ -474,12 +474,13 @@ function Uninstall-UnslothStudio { # 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 is gated on an Unsloth install - # existing (checked BEFORE rm deletes the marker) so an unrelated listener survives. 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 fuser -k 8888/tcp 2>/dev/null; fi; pkill -9 -f ''/root/\.unslot[h]/'' 2>/dev/null; true' + # /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' # 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 diff --git a/studio/scripts/provision_llama_cuda.sh b/studio/scripts/provision_llama_cuda.sh index 29ffc0052e..43779c0d10 100644 --- a/studio/scripts/provision_llama_cuda.sh +++ b/studio/scripts/provision_llama_cuda.sh @@ -172,6 +172,30 @@ if [ ! -d "$LLAMA_DIR/.git" ]; then fi cd "$LLAMA_DIR" || { _restore_prev; exit 0; } +# When rebuilding in-place over an existing git checkout, the whole-dir backup above +# was skipped (_LLAMA_BAK empty) -- but build/ may already hold a working (e.g. CPU) +# llama-server from a prior setup.sh source build. The wipe-on-failure paths below +# would destroy it with nothing to restore, leaving NO server despite the "keeps the +# existing server" promise (a thermal shutdown mid-CUDA-build is a real failure mode +# here). Back up the existing binaries so a failed rebuild can put them back. Only +# bin/ (server + dlopen-ed backends) is needed; cheap since any pre-existing server +# here is the non-CUDA fallback (a CUDA one would have exited at step 0). +_BUILD_BAK="" +if [ -z "$_LLAMA_BAK" ] && [ -x "$SERVER" ]; then + _BUILD_BAK="${LLAMA_DIR}.binbak.$$" + rm -rf "$_BUILD_BAK" 2>/dev/null + cp -a "$LLAMA_DIR/build/bin" "$_BUILD_BAK" 2>/dev/null || _BUILD_BAK="" +fi +_restore_build() { + if [ -n "$_BUILD_BAK" ] && [ -e "$_BUILD_BAK" ] && [ ! -x "$SERVER" ]; then + mkdir -p "$LLAMA_DIR/build" 2>/dev/null + rm -rf "$LLAMA_DIR/build/bin" 2>/dev/null + mv "$_BUILD_BAK" "$LLAMA_DIR/build/bin" 2>/dev/null && log "restored previous llama-server (rebuild failed)" + fi + [ -n "$_BUILD_BAK" ] && rm -rf "$_BUILD_BAK" 2>/dev/null + _BUILD_BAK="" +} + log "building CUDA llama.cpp (arch=$CUDA_ARCH, host=$HCXX) - this takes a few minutes..." _cmake_configure() { cmake -S . -B build -DCMAKE_BUILD_TYPE=Release \ @@ -185,7 +209,7 @@ _cmake_configure() { if ! _cmake_configure; then log "stale/incompatible CMake cache detected; wiping build dir for a clean CUDA configure" rm -rf build - _cmake_configure || { log "cmake configure failed"; cd /; _restore_prev; exit 0; } + _cmake_configure || { log "cmake configure failed"; cd /; _restore_build; _restore_prev; exit 0; } fi # Also builds the targets unsloth-zoo's GGUF exporter needs (llama-mtmd-cli, # llama-gguf-split). Jobs default to ~half the cores (full -j(nproc) CUDA builds @@ -226,10 +250,13 @@ if ! _cmake_build; then # (undefined ggml_cuda_op_* refs); wipe and rebuild clean. log "build failed (likely interrupted/partial); wiping build dir and rebuilding clean" rm -rf build - _cmake_configure || { log "cmake configure failed"; cd /; _restore_prev; exit 0; } - _cmake_build || { log "cmake build failed"; cd /; _restore_prev; exit 0; } + _cmake_configure || { log "cmake configure failed"; cd /; _restore_build; _restore_prev; exit 0; } + _cmake_build || { log "cmake build failed"; cd /; _restore_build; _restore_prev; exit 0; } fi _cmake_build_extras +# Drop the backup on a successful build, or restore the prior server if the rebuild +# yielded none (idempotent; only restores when $SERVER is missing). +_restore_build if is_cuda_server "$SERVER"; then log "CUDA llama-server ready: $SERVER" diff --git a/studio/setup.sh b/studio/setup.sh index 87e99acf53..bf22bea51e 100755 --- a/studio/setup.sh +++ b/studio/setup.sh @@ -1253,11 +1253,15 @@ if [ "$_NEED_LLAMA_SOURCE_BUILD" = true ] && \ fi # ── WSL2 aarch64 + NVIDIA, no nvcc yet: defer to the background CUDA build ── -# install.ps1 builds the CUDA llama-server in the background; without nvcc, -# section 9 could only make a slow CPU server that build discards. With nvcc we -# fall through to section 9; opted out (UNSLOTH_NO_LLAMA_CUDA=1) the CPU build is -# the only server. +# install.ps1 builds the CUDA llama-server in the background AND signals that by +# exporting UNSLOTH_WSL_LLAMA_DEFERRED=1 into this install. ONLY defer when that +# flag is set: a direct in-WSL `unsloth studio update` has no background builder, +# so deferring there would report "CUDA build running in background" while nothing +# builds -- hiding a no-server state. Without the flag we fall through to section 9 +# (a slow CPU server, still better than a phantom background build). With nvcc we +# fall through too; opted out (UNSLOTH_NO_LLAMA_CUDA=1) the CPU build is the only server. if [ "$_NEED_LLAMA_SOURCE_BUILD" = true ] \ + && [ "${UNSLOTH_WSL_LLAMA_DEFERRED:-0}" = "1" ] \ && [ "$_LLAMA_FORCE_COMPILE" != "1" ] \ && [ -z "$_LLAMA_PR" ] \ && [ "${UNSLOTH_NO_LLAMA_CUDA:-0}" != "1" ] \