Skip to content

Fix page over-release in CountRange - #26

Merged
hadashiA merged 1 commit into
mainfrom
fix-countrange-page-release
Jul 11, 2026
Merged

Fix page over-release in CountRange#26
hadashiA merged 1 commit into
mainfrom
fix-countrange-page-release

Conversation

@hadashiA

Copy link
Copy Markdown
Owner

Problem

In TreeWalker.CountRange / CountRangeAsync, the sibling-walk loop reassigns page to the newly acquired right sibling inside the try block, while the finally releases page. So each iteration releases the page it just acquired instead of the page it just finished counting:

  • the start page's reference is never released (refcount leak)
  • every subsequent page gets double-released; when the loop returns, the last page's refcount hits 0 and its buffer is returned to the pool while the entry is still in the page cache map

Any later traversal that touches that dead entry spins forever: TryGet keeps failing (refcount is 0) and Load keeps no-op'ing (the dead entry still occupies the map slot). Since the buffer went back to MemoryPool while still reachable, data corruption is also possible.

A single CountRange call succeeds — the dead entry is only observed by the next traversal — which is why existing tests never caught it. It surfaced as an infinite loop when running CountRange in a benchmark loop.

The start-position retry loop also leaked one reference per cache miss (TryGet into page, which the subsequent TrySearch retry overwrites).

Fix

Snapshot the owned reference per iteration (var currentPage = page) and release that, matching the existing pattern in GetRangeAscending. The retry loop now just calls Load, also matching GetRangeAscending.

Test

Added a regression test that runs CountRange repeatedly over a multi-page range and then reads a key on the range's last page, guarded by a 10s timeout. Before the fix it deadlocks; after the fix the whole suite passes.

🤖 Generated with Claude Code

@hadashiA
hadashiA merged commit 43df1ec into main Jul 11, 2026
1 check passed
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