Skip to content

fix: TrackedEnv drop must close the heed env via prepare_for_closing - #213

Merged
flupkede merged 1 commit into
developfrom
fix/index-rm-windows-holder
Aug 19, 2026
Merged

fix: TrackedEnv drop must close the heed env via prepare_for_closing#213
flupkede merged 1 commit into
developfrom
fix/index-rm-windows-holder

Conversation

@flupkede

Copy link
Copy Markdown
Owner

Root cause of the deterministic Windows index rm failure (todo board #76)

heed 0.20's process-global OPENED_ENV cache stores its own strong Env clone inside the entry, so dropping the last user-side Env leaves the Arc count at exactly 1 (the entry's own) and mdb_env_close never runs. On POSIX: invisible fd + mmap leak. On Windows: data.mdb/lock.mdb stay locked for the process lifetime.

That is the real cause of serve::tests::index_rm_deletes_db_while_serve_holds_real_lmdb_env failing deterministically (os error 32 through the whole 60s retry budget, LMDB registry empty — the holder is invisible to it), and equally of a real codesearch index rm against a running serve never deleting the DB dir. Proven by minimal serve-free repro: open SharedStores → drop → registry empty BUT env_closing_event still Some and data.mdb locked.

Fix

TrackedEnv::drop now calls Env::prepare_for_closing() — heed's one real close path (takes the entry's reference out, closes synchronously) — before unregistering our registry slot. The existing slot-ordering invariant is preserved and now actually holds. Nothing in the codebase clones a raw heed::Env out of a TrackedEnv, so the wrapper is the last user-side reference.

Tests

  • drop_really_closes_heed_env_and_releases_the_files (registry level — heed's OPENED_ENV entry must be gone after drop, db dir deletable)
  • sharedstores_drop_releases_db_dir_for_deletion (production shape, serve-free, instant)
  • Previously failing acceptance test: 3/3 pass in ~0.6s (was 3/3 fail in ~62s each)
  • Full lib suite 612 passed / 0 failed / 21 ignored; clippy + fmt clean
  • Mutation-verified in review: reverting the fix makes both new tests fail with the exact production os error 32

heed 0.20's OPENED_ENV cache holds a strong Env clone inside its entry, so
dropping the last user-side Env leaves the Arc count at 1 (the entry's own)
and mdb_env_close NEVER runs. On POSIX: invisible fd + mmap leak. On Windows:
data.mdb/lock.mdb stay locked for the process lifetime — the real cause of
serve::tests::index_rm_deletes_db_while_serve_holds_real_lmdb_env failing
deterministically (os error 32 through the whole 60s retry budget, LMDB
registry empty: the holder is invisible to it), and equally of a real
'codesearch index rm' against a running serve never deleting the DB dir.

Diagnosed via minimal serve-free repro: open SharedStores, drop, data.mdb
still locked + env_closing_event still Some. TrackedEnv::drop now calls
Env::prepare_for_closing() — heed's one real close path (takes the entry's
reference out, closes synchronously) — before unregistering our registry
slot, preserving the existing slot-ordering invariant, which now actually
holds. No codebase path clones a raw heed::Env out of a TrackedEnv, so the
wrapper is the last user-side reference.

Tests: drop_really_closes_heed_env_and_releases_the_files (registry level),
sharedstores_drop_releases_db_dir_for_deletion (production shape). Previously
failing acceptance test now passes 3/3 in ~0.6s (was: fail in ~62s); full lib
suite 612/612. CHANGELOG [1.3.4] entry added; AGENTS.md LMDB rule extended.
@flupkede
flupkede merged commit 23a2590 into develop Aug 19, 2026
4 of 5 checks passed
@flupkede
flupkede deleted the fix/index-rm-windows-holder branch August 19, 2026 05:57
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