-
Type:
Bug
-
Resolution: Fixed
-
Priority:
Major - P3
-
Affects Version/s: None
-
Component/s: Cursors
-
Storage Engines - Foundations
-
254.101
-
None
-
None
Problem
Use-after-free (SIGSEGV) closing a layered: cursor on a disaggregated leader. __wti_cursor_cache_release launches a cursor-cache sweep while releasing a layered cursor's stable constituent; the sweep reentrantly closes a cached layered cursor and frees that same constituent, then the release dereferences the freed (0xabab...) cursor.
Reproduction
./build/test/csuite/schema_disagg_leader_abort/test_schema_disagg_leader_abort \
-b "$(pwd)/build" -s 8 -T 9 -t 300 -PSD7174404,E14703576 -h WT_TEST.schema_abort.w1
Default 30s run passes; ~300s reproduces. Single-threaded reentrant free, not a cross-thread race.
Evidence (ASan)
ERROR: AddressSanitizer: heap-use-after-free
free: __wt_cursor_close cur_std.c:1157
__clayered_close_cursors cur_layered.c:378
__clayered_close_int cur_layered.c:3035
__wt_session_cursor_cache_sweep session_api.c:135
__wti_cursor_cache_release cur_std.c:822 <- sweep launched here
__clayered_close_cursors cur_layered.c:378
use: __wti_cursor_cache_release cur_std.c:832 (cursor->cache(cursor))
__clayered_close_cursors cur_layered.c:378
alloc: __clayered_open_stable_int cur_layered.c:422
Only reachable with layered cursors: their constituents are cache-participating file cursors and the sweep closes layered cursors recursively.
Suggested fix
Skip the sweep when releasing a layered constituent (owned cursor), or add a session-level guard making the sweep non-reentrant.