Skip to content

emrg: fix Windows installer DeleteFile code 5 — module-holder enumeration + isolated mode - #844

Merged
argszero merged 1 commit into
masterfrom
feature/stop-all-module-holders
Aug 18, 2026
Merged

argszero merged 1 commit into
masterfrom
feature/stop-all-module-holders

Conversation

@argszero

Copy link
Copy Markdown
Owner

Summary

Fixes the persistent Windows installer DeleteFile code 5 on ~/.emrg/install overwrite (host rants 2026-08-18T16:09:45 + 16:24:01, reproduced on v0.2.48).

Root causes (diagnostic-script proof, rant 16:24:01)

  • The lock holder was PID 9280 — a browser-harness child process that loaded install\lib\websockets\speedups.pyd (inherited PYTHONPATH). Restart Manager never reported it (the 2 owners it found were excluded ancestors) → killing the wrong object.
  • CreateFileW probing provably cannot detect DLL module locks: a DELETE + SHARE_NONE probe reported OK while DeleteFile still failed — LoadLibrary image-section locks are only visible via Process.Modules enumeration.
  • stop_all.py ran from install\python-dist\python.exe whose site config could import install\lib → potential self-lock (rant 16:09:45).
  • Kill-mode RM scan hit the 60s timeout (PowerShell Stop-Process hangs on refusing/waiting targets).

Fixes (emrg/_stop_all.py + packaging/make-installer.sh)

  1. find_install_module_holders() — PowerShell Get-Process + $_.Modules.FileName filtered by the install prefix: names the actual processes holding DLL/.pyd locks (with loaded-file list, parent PID, excluded-ancestor tag).
  2. stop_lock_owners() order — module-holder enumeration FIRST (kills each external holder's process tree via taskkill /F /T /PID), then Restart Manager as auxiliary; browser-harness hint preserved.
  3. verify — new module-holder residual category (primary); RM re-scan + createfile-probe kept as auxiliary; any external holder → exit 1 with a named list → installer aborts cleanly.
  4. createfile-probe demoted to supplementary — relabeled from the misleading "lock-probe 0 locked" (it cannot see DLL locks); real verdict comes from module-holders.
  5. Isolated mode — installer runs stop_all with "{PythonExe}" -I "{StopScript}" (ignore PYTHONPATH/site-packages/.pth), so the pure-stdlib script never imports install\lib (self-lock eliminated).
  6. Self-lock final guard — if the probe still reports locked files but neither module-holder nor RM found an external owner, print WARNING: lock holder is the stop_all runtime itself + exit 1 (re-run installer guidance) instead of letting the installer hit code 5.

Verification

  • tests/test_stop_all.py + tests/test_installer_stop.py: 85 passed (new tests pin module-holder enumeration, taskkill /F /T, verify category order, createfile-probe demotion, self-lock guard).
  • Full suite: 941 passed + 1 skipped (942 collected; Agent.md count updated).
  • GUI npm test green; import + CLI OK.

Acceptance (Windows, next release)

stop_all.log shows module-holders: PID ... python.exe (...browser_harness.daemon) loads [speedups...] → killed with its tree → verify has no module-holder → installer overwrites install\ without code 5. Clean/quiet installs unaffected; rm-scan owner detail retained.

…tion + isolated mode (rants 2026-08-18T16:09:45/16:24:01)

@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 (1/3). Both test + test-windows CI PASS (run 32116928996). Reviewed full diff: module-holder enumeration via Get-Process/.Modules (only detector for DLL image-section locks, per host diagnostic evidence PID 9280), taskkill /F /T tree kill, verify module-holder category primary + createfile-probe demoted (supplementary), -I isolated mode in PrepareToInstall (self-lock), self-lock final guard. Local pytest 941 passed + 1 skipped (942 collected), GUI green, import + CLI OK.

@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 (2/3). Independent re-verify: head 96ef83f unchanged, CI test + test-windows both PASS (run 32116928996), MERGEABLE CLEAN. Confirmed in diff: find_install_module_holders()/_parse_module_holders()/_kill_tree_windows() present; stop_lock_owners runs module-holder enumeration before RM; verify has module-holder category before RM re-scan; createfile-probe demoted to supplementary; PrepareToInstall runs python with -I isolated mode; self-lock guard (no external module-holder/RM owner → WARNING + exit 1).

@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 (3/3). Re-verified head 96ef83f (unchanged since 2/3), CI test + test-windows PASS (32116928996), MERGEABLE CLEAN. Three independent cycle reviews complete — merging.

@argszero
argszero merged commit e4f562c into master Aug 18, 2026
2 checks passed
argszero added a commit that referenced this pull request Aug 18, 2026
Co-authored-by: EMRG Evolution <emrg@argszero.dev>
@argszero
argszero deleted the feature/stop-all-module-holders branch August 18, 2026 13:09
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.

1 participant