Repository navigation
Signal the queue's peer under its lock - #105
Merged
Merged
Conversation
The signal callback was chosen outside the lock and called after releasing it, so a peer that retires its end in between is called anyway - it passes the open check and then reaches a callback whose owner has already gone. The open state was published outside the lock for the same fields the peer reads under it. Both now happen under the lock, which means the callback may only wake the peer's run loop and must never re-enter the queue.
This was referenced Aug 14, 2026
Fails on the previous code for the reason that matters: the callback is chosen outside the lock and invoked after it is released, so the lock is free while it runs and a peer can retire its end underneath it.
kasperisager
approved these changes
Aug 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The signal callback is picked outside the lock and invoked after it is released, so a peer that retires its end in that window still gets called. The open state is published outside the lock too, for fields the peer reads under it.
Both move under the lock. The consequence worth knowing is that the callback now runs with the lock held, so it may only wake a run loop - never re-enter the queue - which is what all three platform implementations do.
Split out of #94, where this was tangled up with the transport change. Nothing consumes the queue on main yet, so this stands on its own.