Enqueue reply promise after the send, not before#14
Merged
Conversation
Replaces the rescue-based guard from the previous commit with a simpler ordering: send the command first, then push its reply promise onto @reply_promises — both still under the write lock so queue order keeps matching wire order. A sender cancelled (Async::Stop) or failed mid-send now unwinds before it enqueues anything, so it can never leave an orphaned slot for a later reply to be misrouted onto. This makes the orphan structurally impossible instead of defending against it, and deletes the begin/rescue Exception/delete/reject block entirely. There is no yield between the send and the push, so no reply for the command can be observed before its promise is queued; and a sender cancelled at promise.wait was always safe, since its promise stays in the queue and the matching reply resolves it harmlessly. Tests unchanged in intent; verified they still fail on the naive push-before-send ordering.
bgoRelatel
approved these changes
Jul 16, 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.
Summary
Simplifies the cancellation-safe send path merged in #13. That fix kept the reply promise being pushed onto
@reply_promisesbefore the write and added arescue Exceptionto delete-and-reject it if the send was interrupted. This reorders the two lines instead — send first, then push — so the orphaned-slot state can never exist in the first place, and the rescue block is deleted.Why this is safe in both cancellation windows
send_dataraises before the<<runs, so no promise is ever enqueued — nothing to clean up, no orphan, no misrouting. Structurally impossible rather than defended.shift.resolvefires against a promise nobody is waiting on (a harmless no-op), and the FIFO stays aligned with the wire. Unchanged from before.The one invariant this relies on: nothing yields between
send_datareturning and the push (both are sequential statements inside the lock), so no reply for this command can be observed before its promise is queued. The push stays inside the write lock so queue order keeps matching wire order.Tests
The regression tests from #13 are unchanged in intent and still pass. I verified they still fail (3/3) on the naive push-before-send ordering, so they retain their teeth against this implementation — the reorder, not the tests, is what provides safety. Full suite: 120 runs, 414 assertions, 0 failures.
Note
This supersedes the
rescue Exceptionapproach from #13 (already merged); net effect is a deletion of that block. Builds onmaster.