[eric] windows: stop nsis upgrades hitting "cannot be closed" by reaping app builder children on quit and fixing the dead orphan-killer; bump 1.1.67

- root cause: window-all-closed called killBackend() (windows: taskkill /F) BEFORE before-quit could POST /shutdown-all, so the backend died before running stop_all(), orphaning the bundled vite node.exe; a running node.exe locks its own image at resources\node\x64\node.exe, so the next nsis upgrade cannot overwrite it and surfaces appCannotBeClosed via the file-lock retry path (extractAppPackage.nsh / installUtil.nsh), not the name-based app-running check
- windows-only because mac's killBackend sends SIGTERM, letting uvicorn run its lifespan shutdown -> stop_all(); only since 1.1.64 because app builder first spawned these children on windows in bf6d7a9 (before that they died with WinError 2)
- electron/main.js: drop the premature killBackend() in window-all-closed (will-quit still kills the backend, now AFTER the reap) and raise the pre-quit reap budget from 2s to 10s to cover stop_all's parallel taskkill (up to 5s) + 3s grace
- electron/build/installer-recovery.nsh: replace the customInit orphan-killer (wmic, removed from windows 11 24H2 so it silently no-oped) with a path-scoped powershell Stop-Process; backtick-delimited for valid nsis tokenization, verified the macro compiles with makensis + the bundled nsExec plugin
- mac unaffected: will-quit already kills the backend; the app reap just runs explicitly via /shutdown-all now instead of riding on SIGTERM timing; the .nsh path is windows-only

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Eric
2026-05-26 13:30:05 -07:00
co-authored by Claude Opus 4.7
parent c0d0e012cc
commit 45a97aa05f
+11 -6
View File
@@ -33,8 +33,9 @@
; 1. App is running (user double-clicked installer without quitting)
; → taskkill /F /IM OpenSwarm.exe /T cascades through children
; 2. App crashed and left orphan python.exe / node.exe with no parent
; to taskkill via PID → wmic finds them by ExecutablePath substring
; and deletes them
; to taskkill via PID → PowerShell finds them by image path under
; the install dir and force-kills them (wmic, the old approach, was
; removed from Windows 11 24H2 and silently no-oped there)
;
; Both are safe (filter to install-dir-rooted processes only) and
; both no-op silently if no matching processes exist.
@@ -42,10 +43,14 @@
nsExec::Exec 'taskkill /F /IM OpenSwarm.exe /T'
Pop $0 ; discard exit code; non-fatal if no process matched
; wmic where-clause: match anything under the per-user install dir.
; The single backslash in '%\\Programs\\OpenSwarm\\%' becomes a
; literal backslash after NSIS's escape, then SQL LIKE pattern.
nsExec::Exec 'wmic process where "ExecutablePath like ''%\\Programs\\OpenSwarm\\%''" delete'
; Kill orphaned node/python whose image lives under the install dir (e.g.
; an App Builder vite node.exe that outlived a crash). A running .exe
; locks its own image, which would block the upgrade overwrite and
; surface "cannot be closed". Scoped by path so the user's own
; node/python stay untouched. PowerShell, not wmic, since wmic is gone
; from Windows 11 24H2. NSIS escaping: backtick-delimited so the inner "
; and ' are literals; $$ yields a literal $ (so $$_ becomes PowerShell $_).
nsExec::Exec `powershell -NoProfile -NonInteractive -Command "Get-Process node,python -ErrorAction SilentlyContinue | Where-Object { $$_.Path -like '*\Programs\OpenSwarm\*' } | Stop-Process -Force -ErrorAction SilentlyContinue"`
Pop $0
; Brief pause so Windows kernel releases handles before NSIS tries