Skip to content

Fix release fence ordering in inner_enqueue() to prevent size_approx() race on AArch64 - #172

Open
cppmage wants to merge 1 commit into
cameron314:masterfrom
cppmage:cppmage-fix-tailblock-next-race
Open

Fix release fence ordering in inner_enqueue() to prevent size_approx() race on AArch64#172
cppmage wants to merge 1 commit into
cameron314:masterfrom
cppmage:cppmage-fix-tailblock-next-race

Conversation

@cppmage

@cppmage cppmage commented Aug 15, 2026

Copy link
Copy Markdown

Fixes #171

What changed

Move fence(memory_order_release) in inner_enqueue()'s CanAlloc
branch so it precedes both writes that publish a newly allocated block
(tailBlock_->next = newBlock and tailBlock = newBlock), instead of
only the second one. See #171 for the full root-cause
analysis and repro.

Also expanded the comment at that call site to note that
size_approx() (and any other Block::next-chain traversal) depends
on this ordering too, not just try_dequeue().

Testing

  • Reproduced the original crash on AArch64 with the existing
    size_approx stress test run in a loop (1000 iterations).
  • Confirmed the crash no longer reproduces after the fix under the
    same loop (1000 iterations).
  • Note: the existing size_approx stress test has other pre-existing
    assertion failures, unrelated to this change and not addressed here.

Move fence(memory_order_release) before both writes that publish a
newly allocated block (tailBlock_->next and tailBlock), not just the
second one. size_approx() reaches blocks via the next-chain and never
reads tailBlock, so it wasn't covered by the existing fence placement.

Fixes cameron314#171
@cppmage cppmage changed the title fix: move release fence in inner_enqueue() Fix release fence ordering in inner_enqueue() to prevent size_approx() race on AArch64 Aug 15, 2026
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.

Race condition in inner_enqueue() causes SIGSEGV in size_approx() on AArch64

1 participant