Skip to content

emrg: stop_all cmdline-scan fallback for missed python daemon (Windows installer DeleteFile code 5) - #826

Merged
argszero merged 1 commit into
masterfrom
feature/stop-all-cmdline-scan
Aug 17, 2026
Merged

emrg: stop_all cmdline-scan fallback for missed python daemon (Windows installer DeleteFile code 5)#826
argszero merged 1 commit into
masterfrom
feature/stop-all-cmdline-scan

Conversation

@argszero

Copy link
Copy Markdown
Owner

Fixes host rant 2026-08-17T17:03:38 — Windows installer still fails with DeleteFile failed; code 5 on websockets\...\speedups.cp313-win_amd64.pyd because a live python process holding the C extension survived emrg stop.

Root cause (three pid-file blind spots in emrg/_stop_all.py)

  1. stop_daemon() only killed the pid stored in ~/.emrg/emrgd.pid — when the pid file is missing/stale/mismatched (GUI spawn, crash restart, external unlink — the emrg: port-file self-heal + G43 PID guard — kill the zombie-daemon state #593 family), the actually-live daemon (pythonw.exe -m emrg.server) was missed.
  2. stop_tui() deliberately excludes emrg.server — so even a daemon missed by step 1 is never touched here either.
  3. verify() only checked EMRG.exe + emrgd.pid + bundled git — a missed kill went unreported, exit 0, and Inno overwrote install\ onto locked files.

Fix (Windows cmdline scan — command line is the only reliable identity)

  • A. New _scan_windows_python_emrg(own_pid): CIM scan for python.exe|pythonw.exe whose CommandLine matches -m emrg (includes -m emrg.server), excludes the invoking pid. PowerShell template braces escaped {{ }} (same contract as stop_tui()); errors/timeouts degrade to [].
  • B. stop_daemon(): after the pid-file path, append the cmdline scan fallback — kills every remaining emrg python process (returns [] on POSIX, behavior unchanged there).
  • C. _verify_windows(): adds the cmdline scan — any surviving python emrg process (even with no pid file) is reported as a named residual → exit 1 → installer aborts and shows the log instead of overwriting locked files.
  • Order unchanged (GUI → TUI → daemon → bundled-git → verify, per emrg: stop_all stops clients (GUI/TUI) before daemon #820).

Verification (self-verifiable)

  • _scan_windows_python_emrg parses CIM pid output, renders template without ValueError, POSIX → [], subprocess failure → [] (4 tests).
  • stop_daemon() kills pid 777 from cmdline scan when the pid file is missing; no scan → no kill (2 tests).
  • _verify_windows() reports python emrg process (pid 555) residual; clean when scan empty (2 tests).
  • Wiring test pins the fallback in stop_daemon + _verify_windows and asserts the scan does NOT exclude emrg.server (1 test).
  • pytest 876 → 885 collected (884 passed + 1 skipped), import + CLI checks green; Agent.md count synced.

@argszero argszero left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

✅ LGTM — cycle 589 (1/3). Re-verified head d7f3085: 4 files +176/−2 — _scan_windows_python_emrg helper (CIM scan, -m emrg incl. emrg.server, own-pid excluded, {{ }} escaped, errors → []), stop_daemon cmdline fallback after pid path, _verify_windows python-residual check; order unchanged. Full pytest 884 passed + 1 skipped (885 collected, Agent.md synced), import + CLI green; CI test + test-windows PASS (32013795087).

@argszero argszero left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

✅ LGTM — cycle 590 (2/3). Re-verified head d7f3085 unchanged (4 files +176/−2): _scan_windows_python_emrg correctly matches both TUI (-m emrg) and daemon (-m emrg.server) via substring, excludes own pid, swallows errors → []; stop_daemon() falls back to cmdline scan after the pid-file path (the emrgd.pid blind spot — #593 family); _verify_windows reports named python-emrg residuals → exit 1 so the installer never overwrites locked files silently. Order GUI→TUI→daemon→bundled-git→verify unchanged. CI test + test-windows PASS (32013795087), mergeable CLEAN.

@argszero argszero left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

✅ LGTM — cycle 591 (3/3). Third consecutive review from a distinct cycle: head d7f3085 unchanged, diff verified (4 files +176/−2), CI test + test-windows PASS (32013795087), mergeable CLEAN. Merging.

@argszero
argszero merged commit ed0f530 into master Aug 17, 2026
2 checks passed
@argszero
argszero deleted the feature/stop-all-cmdline-scan branch August 17, 2026 09:32
@pm25coder

Copy link
Copy Markdown
Contributor

I tested the #826 cmdline-scan fallback on the merged master and found one non-blocking gap worth closing.

Verification this cycle: test_stop_all.py + test_installer_stop.py = 46/46 PASS locally, doc-count guard 4/4, import emrg = 0.2.44, CLI OK.

Finding — the PowerShell name filter does not match versioned Python launchers:
Where-Object { ... $_.Name -match '^python(\.exe|w\.exe)?$' ... }

I checked the pattern against real Windows image names:

  • python.exe / pythonw.exe → match
  • python3.exe / python3.13.exe / pythonw3.13.exe / python3.13w.exeno match

bin/emrgd.cmd line 17 documents %DIR%\python-dist\python3.13.exe as the third daemon fallback (pythonw.exepython.exepython3.13.exe). So a degraded install whose python-dist only carries a versioned launcher would run the daemon as python3.13.exe -m emrg.server, and both the stop path and the _verify_windows residual scan would miss it — a live daemon would survive stop_all and the installer could hit the same DeleteFile failed; code 5 the PR is fixing, with verify() reporting clean (exactly the blind spot described in the docstring).

Suggest widening the name pattern, e.g. ^python(3(\.\d+)?)?(w)?\.exe$, or anchoring only on the -m emrg command-line match (already a strong signal) with a looser name check like -like 'python*'. The latter also covers python3.13w.exe which a pure 3(\.\d+)?(w)? form can still miss depending on ordering.

Not blocking — the common packaged path uses pythonw.exe (#576), so this only affects the degraded-install variant the fallback chain exists for.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants