Skip to content

fix(webrtc-websys): defer data channel callback wakes - #6558

Open
yexiyue wants to merge 1 commit into
libp2p:masterfrom
yexiyue:fix/webrtc-websys-callback-lifecycle-pr
Open

fix(webrtc-websys): defer data channel callback wakes#6558
yexiyue wants to merge 1 commit into
libp2p:masterfrom
yexiyue:fix/webrtc-websys-callback-lifecycle-pr

Conversation

@yexiyue

@yexiyue yexiyue commented Jul 24, 2026

Copy link
Copy Markdown

Description

Fix a lifetime and re-entrancy bug in the WebRTC WebSys data-channel callbacks.

PollDataChannel previously allowed a queued browser event to invoke a wasm-bindgen closure after its Rust owner had been dropped. Waking the task synchronously from the callback could also re-enter polling while wasm-bindgen still held a mutable borrow of that closure. Either path could panic with closure invoked recursively or after being dropped.

Keep the RTCDataChannel and its registered closures in a shared owner, remove the handlers before the final owner is released, and defer waker notifications until after the JavaScript callback returns.

Fixes #6551.

AI Assistance Disclosure

Tools used (required — write none if no AI was used): Codex (GPT-5)

Attestation (required):

  • I have read every line of this diff, understand what it does, and can explain it in review.

Notes & open questions

Validation performed:

  • cargo fmt --check -p libp2p-webrtc-websys
  • cargo check -p libp2p-webrtc-websys --target wasm32-unknown-unknown
  • Browser-to-browser WebRTC relay transfer testing: the wasm-bindgen callback exception no longer occurs and file transfer completes.

The 8 KiB framing behavior encountered during the same investigation is intentionally out of scope and is tracked in #6557.

No standalone automated regression test was added because reproducing the stale browser-event timing requires an actual browser WebRTC runtime. No user-facing documentation change is needed. I have not added a changelog entry for this internal correctness fix; happy to add one if maintainers prefer it.

Change checklist

  • I have performed a self-review of my own code
  • I have made corresponding changes to the documentation
  • I have added tests that prove my fix is effective or that my feature works
  • A changelog entry has been made in the appropriate crates

@jxs jxs left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi and thanks for this,
but can you reply to the PR form?

@yexiyue

yexiyue commented Jul 24, 2026

Copy link
Copy Markdown
Author

Thanks — I have filled in the PR form now.

For validation, besides the wasm check, I reproduced the failure and verified this fix with a browser-to-browser WebRTC relay transfer in SwarmDrop (which embeds libp2p-webrtc-websys). The prior closure invoked recursively or after being dropped exception no longer occurs and the transfer completes. For a reviewer who wants to reproduce the integration flow manually, the public test page is: https://swarm-apps.github.io/SwarmDrop/try/

I also looked at adding an upstream regression test. The existing interop-tests WebRTC Direct path provides a browser-to-native ping harness, but this bug depends on a queued RTCDataChannel event arriving after the final Rust stream owner has been dropped; I have not found a deterministic way to force that browser scheduling boundary in the current harness. I would be happy to extend the preferred browser test setup if you have a recommendation, or add a focused test seam if you would prefer that over the end-to-end validation record.

yexiyue added a commit to yexiyue/rust-libp2p that referenced this pull request Jul 25, 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.

webrtc-websys: RTCDataChannel callbacks can panic after stream teardown

2 participants