Smaller pinned appends free capacity without waking waiting pin acquisitions
perfloop-oss/chroma · MISSED NOTIFICATION
https://perfloop.ai/t/oss/case_3rjc0regrn
Verdict
VERIFIED · settled 2026-10-13 · pull request opened as chroma-core/chroma#7904
What happened: The assertion is violated on the comparison and satisfied with this change.
Hypothesis
Submitting a pinned append smaller than its reservation can free capacity without waking tasks waiting to acquire a pin. If another pin keeps the fragment open, those tasks can stay asleep even though their reservations now fit. No occurrence rate or delay has been measured.
The supported public operations are LogWriter::acquire_fragment_pin and append_many_with_options with the resulting pin. A reservation is an upper bound: FragmentPin::reserves accepts byte_count <= reserved_bytes at batch_manager.rs:117–119. FragmentPin::consume takes its coordination reference and releases the reserved bytes at 121–149. Its later Drop therefore returns without issuing the notify_waiters used by an explicitly dropped pin at 162–182. For accepted work, push_work only adds metadata and work at 398–399; it does not notify capacity waiters.
BatchManager::acquire_fragment_pin enables its notification before checking writers_active and can_reserve, then awaits that notification when capacity does not fit at 320–351. This correctly closes the registration gap, but does not supply a notification for the consumption event. OnceLogWriter::append next calls take_work. If another pin remains, take_work returns at 425–426 without notifying or starting a write. Thus neither publication nor its finish_write notification is available to repair this ordering while that other pin stays live.
A deterministic Case witness can use a ten-byte fragment limit. Hold a one-byte pin, acquire an eight-byte pin, and poll two one-byte acquisition futures until both have enabled their notifications and rejected the occupied nine-byte state. Submit an admitted one-byte append through the public append_many_with_options API using the eight-byte pin. Keep the first pin live. Occupied capacity is now two bytes, with no active writer, so both one-byte reservations fit, but neither waiting acquisition receives a wakeup. Retain wake counts, the enabled futures, and the authoritative capacity state; a timeout alone is insufficient. Verify that the real take_work pin guard prevents publication and that no pending notification can resume those futures. The repaired ordering must let both acquisitions complete before releasing the held pin. Explicit pin drop, full-capacity waits, publication completion, and generation shutdown are separate regression controls.
Confidence is medium from source inspection; no ordering reproduction has been run. The public pin contract at writer.rs:321–335 and the accepted smaller-payload check support this operation. The change is internal and requires no new public types, options, or storage protocol.
Change to test: Make pin consumption notify enabled capacity waiters after its final admission and queue update, as explicit pin drops do. Preserve pin generation ownership, byte-capacity rules, and the rule that publication waits until every outstanding pin resolves.
Where it lives
perfloop-oss/chroma · rust/wal3/src/writer.rs
Evidence
The assertion is violated on the comparison and satisfied with this change: `For a live LogWriter with a 10-byte fragment limit, no active writer or shutdown, and one 1-byte pin plus one 8-byte pin occupying 9 bytes, a 1-byte append_many_with_options using the 8-byte pin must wake and admit two already-registered 1-byte acquire_fragment_pin calls before the first pin is released; the append must remain pending while any pin is live.`
Checks: 4 of 4 passed. Verification: no defect found.
Timeline
2026-10-13· Case opened2026-10-13· Case closed2026-10-13· Case closed2026-10-13· PR opened