Summary
In browsers, libp2p-webrtc-websys can panic from an RTCDataChannel event callback after its Rust stream has been torn down:
Uncaught Error: closure invoked recursively or after being dropped
... at RTCDataChannel.<callback>
Root cause
PollDataChannel registers Rust wasm-bindgen closures as persistent RTCDataChannel event handlers. A browser may dispatch an event that was queued before the final Rust stream clone is dropped. If the corresponding Closure has already been released, the stale JavaScript handler invokes a dropped closure.
Calling AtomicWaker::wake() synchronously from the Web API callback can also re-enter polling while wasm-bindgen still holds a mutable borrow of that callback closure.
Proposed fix
- Keep the DataChannel and all registered event callbacks in a shared owner for the lifetime of the final stream clone.
- Detach each browser event handler before that owner releases its closures.
- Defer waker notifications until the Web API callback has returned.
Validation
A focused implementation is available in #6558. It passes the wasm32 build check and removes the browser callback exception in browser-to-browser WebRTC relay transfer testing; the same transfer completes successfully.
The relay frame-size failure found during this investigation is independent and tracked separately in #6557.
Summary
In browsers, libp2p-webrtc-websys can panic from an RTCDataChannel event callback after its Rust stream has been torn down:
Root cause
PollDataChannel registers Rust wasm-bindgen closures as persistent RTCDataChannel event handlers. A browser may dispatch an event that was queued before the final Rust stream clone is dropped. If the corresponding Closure has already been released, the stale JavaScript handler invokes a dropped closure.
Calling AtomicWaker::wake() synchronously from the Web API callback can also re-enter polling while wasm-bindgen still holds a mutable borrow of that callback closure.
Proposed fix
Validation
A focused implementation is available in #6558. It passes the wasm32 build check and removes the browser callback exception in browser-to-browser WebRTC relay transfer testing; the same transfer completes successfully.
The relay frame-size failure found during this investigation is independent and tracked separately in #6557.