Skip to content

Fix two of the close-flush data-loss bugs (#116 ported to main) - #139

Merged
lann merged 1 commit into
mainfrom
close-flush-fixes
Aug 6, 2026
Merged

Fix two of the close-flush data-loss bugs (#116 ported to main)#139
lann merged 1 commit into
mainfrom
close-flush-fixes

Conversation

@lann

@lann lann commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Port of #116 (opened against the pre-migration tree; superseded by this PR) onto main. #125 is now fully diagnosed: the libwebrtc reference peer is blameless. Its immediate close-after-send (spec-legal; libwebrtc flushes before the SCTP reset per RFC 8831 §6.7) coalesces the tail DATA and the reset RECONFIG into one burst, and three distinct receiver-side bugs mishandled it. This PR fixes two.

Fixed here

  1. rtc-sctp discarded received-but-undelivered messages on an incoming stream reset (reference-x-wasmtime, answerer: receive: closed). reset_streams_if_anyunregister_stream dropped the stream's reassembly queue with reassembled-but-unread messages inside, before the driver polled the pending Readable events. Fixed by sctp: don't discard received-but-undelivered data on incoming stream reset lann/rtc#1, rebased onto upstream master (rev 89f518ea).
  2. Reference peer wait_open rejected an already-closing incoming channel (wasmtime-x-reference, answerer: channel closed before open). A remote-announced channel that reads closing/closed was necessarily open first and its messages are already queued; open→send→close can land inside one 25 ms poll interval. Remote channels now count that state as opened; locally created channels still fail.

Also: recv_sequence failures (suite body + reference peer) now report (after N of M messages), which is what made the diagnosis tractable.

Dependency shape (differs from #116)

#116 used [patch.crates-io]; that is no longer viable and this PR uses pinned git dependencies instead:

So both workspace deps resolve from one lann/webrtc branch (rtc-sctp-reset-undelivered-data, rev 15755c6b) whose only delta from upstream webrtc master is the rtc submodule pointed at lann/rtc#1's rev. One source means the direct rtc dependency (wasip3-impl) and the wasmtime host's transitive rtc-sctp are the same package — a split-source attempt produced exactly the expected type-identity mismatch in rtc-ct-driver (its rtc:: values feed webrtc APIs). This moves the stack from released 0.20.0 to master's 0.21.0 (the crypto-provider migration); no code changes were needed. Reopens #120: unwind the pins once releases including the fix ship.

Remaining (not fixed here)

  1. The webrtc driver delivers a data-channel close ahead of already-received messages — webrtc 0.20 driver delivers data-channel close ahead of already-received messages (E18 bug 3) #117 (mechanism verified still present on webrtc master: the driver delta since 0.20.0 is only non_exhaustive match arms). It did not reproduce in 20 verification iterations, plausibly because the reference offerer's 20 ms send pacing (from Migrate the conformance suite onto the polymorph:test harness #135's mitigations) prevents the DATA+RECONFIG coalescing that triggers it.

Verification

Closes #125. Supersedes #116.

Issue #125's close-flush data loss is fully diagnosed: the libwebrtc
reference peer is blameless. Its immediate close-after-send (spec-legal;
libwebrtc flushes before the SCTP reset per RFC 8831 section 6.7)
coalesces the tail DATA and the reset RECONFIG into one burst, and three
distinct receiver-side bugs mishandled it. This fixes two:

1. rtc-sctp discarded received-but-undelivered messages on an incoming
   stream reset (reference-x-wasmtime, `answerer: receive: closed`):
   reset_streams_if_any -> unregister_stream dropped the stream's
   reassembly queue with reassembled-but-unread messages inside, before
   the driver polled the pending Readable events. Fixed by lann/rtc#1
   (rebased onto upstream master, rev 89f518ea).

2. The reference peer's wait_open rejected an already-closing incoming
   channel (wasmtime-x-reference, `answerer: channel closed before
   open`): a remote-announced channel that reads closing/closed was
   necessarily open first and its messages are already queued —
   open->send->close can land inside one 25 ms poll interval. Remote
   channels now count that state as opened; locally created channels
   still fail.

Bug 3 (the webrtc driver delivers a data-channel close ahead of already-
received messages) remains open as #117; the jco-node analog is #124.

The rtc fix rides new git pins replacing the crates.io 0.20.0 versions:
webrtc consumes rtc as an in-repo submodule path dependency, which no
version requirement or [patch] can redirect, so both workspace deps
resolve from one lann/webrtc branch (rev 15755c6b) whose only delta from
upstream webrtc master is that submodule pointed at lann/rtc#1's rev.
One source means the direct rtc dependency (wasip3-impl) and the
wasmtime host's transitive rtc-sctp are the same package. This moves the
stack from released 0.20.0 to master's 0.21.0 (unreleased, the crypto-
provider migration); no code changes were needed. Reopens #120 (unwind
the pins once releases including the fix ship).

Also: recv_sequence (suite body) and the reference peer's close-flush
receive loop report `(after N of M messages)` on failure, so partial
delivery is distinguishable from a receive path that never yielded.

Gates: just check, just test, examples::test-webrtc-composed, and the
full conformance run (loopback + interop, 304 results, 0 failing, 1
expected-fail: #123, matrices unchanged) all pass. Flake check: 10
further interop pair-suite iterations each of reference-x-wasmtime and
wasmtime-x-reference - 240 case results, 0 failures, channel-close-flush
20/20 (the shapes fixed here reproduced on roughly a third of runs
before).

Closes #125.
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.

Undiagnosed data loss: messages sent before close by the libwebrtc reference offerer sometimes never arrive

1 participant