Skip to content

Fix flaky CI: compaction filter race and iterator use-after-free - #13

Merged
benoitc merged 2 commits into
masterfrom
harden-compaction-filter-tests
Jun 14, 2026
Merged

benoitc merged 2 commits into
masterfrom
harden-compaction-filter-tests

Conversation

@benoitc

@benoitc benoitc commented Jun 14, 2026 •

Copy link
Copy Markdown
Contributor

Two flaky/broken-CI fixes surfaced by the PR #12 merge.

1. Compaction filter tests (linux-shared-libs)

filter_key_contains_test flaked: a _session_ key survived a forced compaction. The rule tests used compact_range(undefined, undefined, force), which can trivial-move L0 files to the bottommost level without rewriting them, so the compaction filter never runs and matching keys aren't deleted. Deletions actually came from background auto-compactions, making the outcome timing-dependent.

Fix: give compact_range explicit key bounds (plus a short settle after flush) in the 8 deletion/transform-asserting tests, matching the pattern already used by value_empty, always_delete, and column_family. A bounded range forces a real merge that runs the filter.

2. Use-after-free in column-family and transaction iterators (macOS segfault)

transaction:cf_iterators_test segfaulted intermittently on macOS. A column-family iterator stored only a reference to the DbObject, not the ColumnFamilyObject. Once the erlang CF handle went out of scope, the BEAM GC could free the ColumnFamilyObject (whose destructor calls DestroyColumnFamilyHandle) while an open iterator still referenced that CF; the next iterator_move dereferenced freed memory in DBIter::Seek. The same applies to a transaction iterator and its transaction (whose write batch backs the iterator's delta).

Fix: pin the column family (and, for transaction iterators, the transaction) with enif_keep_resource for the iterator's lifetime, released in ~ItrObject after the iterator is deleted.

Reproduced under OTP 27 on macOS (forcing GC with the handle dropped crashes immediately in DBIter::Seek); with the fix, 10000 iterations run clean. The test is no longer skipped on macOS.

filter_key_contains_test flaked on the linux-shared-libs CI job: a
_session_ key survived the forced compaction. The rule tests relied on
compact_range(undefined, undefined, force), which can trivial-move L0
files to the bottommost level without rewriting them, so the compaction
filter never runs and matching keys are not deleted. Background
auto-compactions usually filtered the data first, making the outcome
timing-dependent.

Give compact_range explicit key bounds (and a short settle after flush)
in the 8 deletion/transform-asserting tests, matching the pattern
already used by the value_empty, always_delete, and column_family tests.
A bounded range forces a real merge that runs the filter. The
keep-asserting handler tests are unaffected and left as-is.
@benoitc benoitc changed the title Harden compaction filter tests against compaction race Fix flaky CI: harden compaction filter tests, restore macOS transaction skip Jun 14, 2026
transaction:cf_iterators_test segfaulted intermittently on the macOS CI
runner. Root cause: a column-family iterator stored only a reference to
the DbObject, not to the ColumnFamilyObject. Once the erlang column
family handle went out of scope, the BEAM garbage collector could free
the ColumnFamilyObject, whose destructor calls DestroyColumnFamilyHandle,
while an open iterator still referenced that column family. The next
iterator_move then dereferenced freed memory inside DBIter::Seek. The
same applies to a transaction iterator and its transaction, whose write
batch backs the iterator's delta.

Pin the column family (and, for transaction iterators, the transaction)
with enif_keep_resource for the iterator's lifetime, releasing them in
~ItrObject after the iterator is deleted. enif_keep_resource is used
rather than the ReferencePtr/close-request path, which would block a
scheduler in AwaitCloseAndDestructor when the handle is collected by GC.

Reproduced under OTP 27 on macOS (forcing GC with the handle dropped
crashes immediately); with the fix, 10000 iterations run clean.
@benoitc
benoitc force-pushed the harden-compaction-filter-tests branch from ff87632 to d74f88c Compare June 14, 2026 13:53
@benoitc benoitc changed the title Fix flaky CI: harden compaction filter tests, restore macOS transaction skip Fix flaky CI: compaction filter race and iterator use-after-free Jun 14, 2026
@benoitc
benoitc merged commit cb270dd into master Jun 14, 2026
8 checks 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