Repository navigation
fix(dialog): end the INVITE of an aborted do_invite_async task - #205
Merged
yeoleobun merged 3 commits intoOct 12, 2026
Merged
Conversation
yeoleobun
added a commit
to tgeorge06/rsipstack
that referenced
this pull request
Oct 12, 2026
Create the INVITE cleanup guard before spawning so an abort before the first poll removes the early dialog without sending a request. Run the existing CANCEL operation independently until its response or transaction timeout, rather than dropping it after two seconds or an INVITE final response. Keep waiting for the INVITE final response and ACK/BYE cleanup. Add regressions for immediate abort and CANCEL retransmission beyond the old deadline and after an INVITE final response. All three fail on the original PR; 426 library tests and the platform-embassy compile check pass with this fix. Refs restsend#204, restsend#205.
do_invite_async drove the INVITE in a spawned task with no drop guard. Aborting that task before the final response dropped the transaction and left the early dialog registered in the layer: no CANCEL, a 2xx was neither ACKed nor ended with a BYE, and the dialog stayed in Calling or Early. The task now holds the same DialogGuardForUnconfirmed as do_invite, so an aborted task ends the INVITE like a dropped do_invite future: CANCEL at once in Trying or Early, on the first provisional in Calling (RFC 3261 section 9.1), ACK + BYE for a 2xx, and the layer entry is removed.
Create the INVITE cleanup guard before spawning so an abort before the first poll removes the early dialog without sending a request. Run the existing CANCEL operation independently until its response or transaction timeout, rather than dropping it after two seconds or an INVITE final response. Keep waiting for the INVITE final response and ACK/BYE cleanup. Add regressions for immediate abort and CANCEL retransmission beyond the old deadline and after an INVITE final response. All three fail on the original PR; 426 library tests and the platform-embassy compile check pass with this fix. Refs restsend#204, restsend#205.
yeoleobun
force-pushed
the
fix/do-invite-async-drop-guard
branch
from
October 12, 2026 12:48
02dcae9 to
d1ebf28
Compare
yeoleobun
added a commit
that referenced
this pull request
Oct 12, 2026
Create the INVITE cleanup guard before spawning so an abort before the first poll removes the early dialog without sending a request. Run the existing CANCEL operation independently until its response or transaction timeout, rather than dropping it after two seconds or an INVITE final response. Keep waiting for the INVITE final response and ACK/BYE cleanup. Add regressions for immediate abort and CANCEL retransmission beyond the old deadline and after an INVITE final response. All three fail on the original PR; 426 library tests and the platform-embassy compile check pass with this fix. Refs #204, #205.
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.
Fixes #204.
Problem
DialogLayer::do_invite_asyncdrives the INVITE in a spawned task (src/dialog/invitation.rs:786-787at currentmain, 6fd9414) that holds no drop guard. Aborting that task before the final response drops the INVITE client transaction: no CANCEL, a 2xx is neither ACKed nor ended with a BYE, the dialog stays inCallingorEarly, and its early entry stays in the dialog layer.do_invitehas handled the same drop correctly since #171.Expected
The same as a dropped
do_invitefuture. RFC 3261 §9.1:and a 2xx that the CANCEL did not prevent is ACKed and ended with a BYE (§9.1, §15).
Fix
The spawned task now holds the same
DialogGuardForUnconfirmedthatdo_inviteuses (invitation.rs:186-339), set up exactly as indo_invite: the guard owns the transaction whileprocess_inviteruns, is disarmed (dialog = None) when it returns, and the transaction is taken back for the Accepted-state drainer. On abort the guard's existingDropruns: CANCEL at once inTrying/Early, on the first provisional inCalling, ACK + BYE for a 2xx, layer entry removed. +19 / -2 lines insrc/dialog/invitation.rs; the rest of the +81 / -2 is tests.Unchanged on purpose:
JoinHandlewithoutabort()still detaches the task, which keeps running. Onplatform-embassythere is noabort(), so nothing changes there.Transaction::receiveis not cancel-safe: an abort that lands whilereceive()is processing a 2xx can still lose it, exactly as for a droppeddo_invitefuture today. That is a separate, shared issue.Contract / coverage
do_invite_asynctask aborted before the final response:CallingCallingEarlyTests
src/dialog/tests/test_cancel_2xx_race.rs, against a raw UDP peer:test_aborted_invite_task_in_calling_is_cancelled_after_the_180,test_aborted_invite_task_in_calling_2xx_is_acked_and_byed,test_aborted_invite_task_in_early_is_cancelled. Each also asserts the layer is empty afterwards. Onmain(6fd9414) all three fail:timeout waiting for CANCEL(both CANCEL cases) andtimeout waiting for ACK(the 2xx case).Checks
cargo test --features bench: 423 lib tests passed, 0 failed (420 onmainplus the 3 new ones), and 65 doc tests passed. Plaincargo testpasses too.cargo check --no-default-features --features platform-embassy: no warnings, as onmain.cargo clippy --features bench --all-targets: the same output as onmain, none in the changed code. (Onmainit stops at aclippy::never_looperror insrc/dialog/tests/test_refer_notify.rs:98, unrelated to this PR; with-A clippy::never_loopthe warnings are the same as onmain.)cargo fmt --check: clean.InviteDialog::cancel()returnsOk(())and does nothing: UAC before the first provisional, and any UAS dialog #197's PR and of fix(transaction): answer a CANCEL after a final response with its own 200 #199; merges cleanly with both.