fix(cua-driver-rs)(install): kill orphan cua-driver daemons after binary swap (install.ps1 + install-local.ps1) - #1689
Conversation
…ary swap (install.ps1 + install-local.ps1) User report after PR #1687 (rename-out-of-way): re-installing leaves the previous in-memory daemon running. That daemon keeps serving requests + drawing its overlay window from the OLD code until reboot. Surfaces as "the bug I just fixed is still there" because the binary on disk is new but the running process is pre-fix. Repro on the reporter's machine had THREE orphan cua-driver.exe processes accumulated from successive install-local.ps1 + autostart kick runs. Two scripts get the same fix, shared via a duplicated function pair (install.ps1 is fetched via `irm | iex` so it can't dot-source — the duplication is intentional, marked with KEEP IN SYNC markers): - Stop-CuaDriverDaemons: schtasks /End → taskkill /F /IM → returns any process that survived (those need elevation to kill). - Show-CuaDriverDaemonSurvivors: prints a hint pointing the user at an elevated `taskkill` one-liner. install.ps1 runs the pair right before the autostart-registration block. install-local.ps1 runs it after the binary rename, replacing the inline block that PR #1687 added (functionally identical, just factored out for the share-the-logic story). Knock-on: because `cua-driver update --apply` invokes install.ps1 (production curl-installer) under the hood, the update path inherits this behaviour for free. Verified end-to-end on Windows with 3 orphan daemons + 1 High-IL daemon from the autostart task: 2 of 3 die cleanly (Medium-IL kill works), 1 survives + the Note hint fires pointing the user at `taskkill /IM cua-driver.exe /F` from an elevated shell.
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
…uaDriverInstall.psm1 (true single source) PR feedback on #1689: "use a psm to share" instead of the KEEP-IN-SYNC duplication. New module at libs/cua-driver/scripts/CuaDriverInstall.psm1 owns: - Stop-CuaDriverDaemons (schtasks /End -> taskkill /F /IM -> return survivors) - Show-CuaDriverDaemonSurvivors (warn + hint on Medium-IL kill that couldn't reach a High-IL daemon) - Import-CuaDriverInstallModule (helper for picking on-disk vs network load; used by install.ps1's bootstrap) Two load paths: install-local.ps1 - checked-out tree, .psm1 is right there on disk next to it. One liner: Import-Module $ScriptDir/CuaDriverInstall.psm1 -Force. install.ps1 - fetched via `irm | iex`, no file on disk. Inline bootstrap function tries on-disk first ($PSScriptRoot, populated when run from a checked-out tree / .ps1 file on disk), then falls back to Invoke-RestMethod against the same .psm1 on GitHub raw + Import-Module from a temp file. Module stays in memory after the temp file is removed. End-to-end verified on Windows: ==> killing previous cua-driver processes (best-effort; High-IL needs admin) Note: 1 cua-driver process(es) still running after best-effort kill (pid: 14152). They are likely High-IL (spawned by RunLevel=Highest autostart task). From an elevated PowerShell: taskkill /IM cua-driver.exe /F Or just reboot. Until they exit, the OLD binary keeps running. Two-on-three orphan daemons cleaned (Medium-IL); the High-IL autostart-spawned survivor correctly reported. Same behaviour as the duplicate-in-both-files version from PR #1689 but now there's a single canonical definition.
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughThis PR extracts daemon-cleanup logic into a shared PowerShell module ( ChangesDaemon Cleanup Refactoring
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…install-common.sh (matches PowerShell .psm1 pattern) PR #1689 just extracted the equivalent Windows logic into CuaDriverInstall.psm1. Same single-source-of-truth treatment for the sh installers — and rename the PowerShell module to _install-common.psm1 so the two halves share the underscore-prefixed `internal helper` naming convention used by the other _install-*.{sh,ps1} files. New shared file: libs/cua-driver/scripts/_install-common.sh Functions: stop_cua_driver_daemons, show_cua_driver_daemon_survivors. Loaded from on-disk first (when run from a checked-out tree) or from GitHub raw via curl when install.sh runs as `curl ... | bash`. Consumers updated to source it: - _install-rust.sh (production Rust delegate; on-disk + network fallback) - _install-local-rust.sh (dev-build Rust installer; on-disk only) - _install-local-swift.sh (dev-build Swift installer; same kill covers both since both binaries bake the `cua-driver` name) macOS LaunchAgent plist names (verified from _install-local-*.sh): - Rust: ~/Library/LaunchAgents/com.trycua.cua-driver-rs.plist - Swift: ~/Library/LaunchAgents/com.trycua.cua_driver_daemon.plist Linux systemd unit (verified from _install-local-rust.sh): - cua-driver-rs.service One pkill -x cua-driver covers both Rust and Swift binaries since both exec under the same product name; no need for a per-backend kill variant. cua-driver-uia is Windows-only so it never appears on Unix hosts and isn't probed here. bash -n passes on all touched files. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Summary
After PR #1687 (`install-local.ps1` rename-out-of-way), re-installs leave the previous in-memory daemon running. It keeps serving requests + drawing its overlay window from the OLD code until reboot — which surfaces as "the bug I just fixed is still there" even though the binary on disk is the new build.
Reporter's machine on dogfood: 3 orphan `cua-driver.exe` processes accumulated from successive `install-local.ps1` + `autostart kick` rounds. Top one stuck in the topmost band (from before PR #1688's Z-order fix), drawing the cursor overlay above the user's terminal.
Fix
Both `install.ps1` (production curl-installer) and `install-local.ps1` (dev) now call a shared kill helper after the binary swap. Same function pair in both files, marked with `KEEP IN SYNC` because `install.ps1` is fetched via `irm | iex` and can't dot-source.
```powershell
function Stop-CuaDriverDaemons {
# 1. schtasks /End — SYSTEM-level kill, reaches High-IL processes
& schtasks.exe /End /TN "cua-driver-serve" 2>$null | Out-Null
# 2. taskkill /F /IM — Medium-IL backstop
& taskkill.exe /F /IM "cua-driver.exe" /T 2>$null | Out-Null
& taskkill.exe /F /IM "cua-driver-uia.exe" /T 2>$null | Out-Null
# 3. Return survivors so caller can warn
return @(Get-Process -Name "cua-driver","cua-driver-uia" -ErrorAction SilentlyContinue)
}
```
Plus `Show-CuaDriverDaemonSurvivors` prints a clear hint when a High-IL daemon (e.g. spawned by the RunLevel=Highest autostart task) survives the Medium-IL kill — pointing the user at `taskkill /IM cua-driver.exe /F` from an elevated shell.
Knock-on benefit:
cua-driver update --applyAlready shells out to install.ps1, so the update path inherits this for free.
Verified end-to-end on Windows
Before: 3 cua-driver.exe orphans (pid 14152 + 2676 + 12380).
After `install-local.ps1`:
```
==> killing previous cua-driver processes (best-effort; High-IL needs admin)
Note: 1 cua-driver process(es) still running after best-effort kill (pid: 14152).
They are likely High-IL (spawned by RunLevel=Highest autostart task).
From an elevated PowerShell:
taskkill /IM cua-driver.exe /F
Or just reboot. Until they exit, the OLD binary keeps running.
```
2 of 3 orphans cleaned; the 1 High-IL survivor is correctly flagged.
Test plan
🤖 Generated with Claude Code
Summary by CodeRabbit