Skip to content

webrtc: release taken-over sessions' UDP sockets - #54

Merged
Rust-KVM merged 1 commit into
devfrom
claude/webrtc-session-close
Oct 11, 2026
Merged

Rust-KVM merged 1 commit into
devfrom
claude/webrtc-session-close

Conversation

@Rust-KVM

@Rust-KVM Rust-KVM commented Oct 11, 2026 •

Copy link
Copy Markdown
Owner

Requested by 4c · project thread

Summary

Before: every time a browser tab took over the session, the old session's WebRTC peer connection stayed alive on the device even after pc.close(). Each one kept about three UDP sockets open (one ICE host candidate per local address), so rustkvm_app's fd count grew by ~3.5 per session (66 → 87 → 108 over two rounds of six take-overs in the round-4 web UI test).

After: the old peer connection is dropped once it is closed and removed, so its ICE agent and candidate sockets are released.

webrtc-util's UdpSocket::close is a no-op; a UDP conn only closes when its last Arc drops. The on_data_channel handler, owned by the peer connection, captured a Session clone holding Arc<RTCPeerConnection>, and DataChannelManager passed that Session on into the data channel callbacks. The connection therefore held a reference to itself and was never dropped.

How

app/src/webrtc.rs: the on_data_channel handler now gets a Session clone with peer_connection = None. Data channel routing only uses the session id and channels; the only users of Session::peer_connection (exchange_offer, add_ice_candidate, and the take-over close in webrtc_handlers.rs / webrtc.rs) read the Session stored in AppState, which still holds the connection.

Testing

  • cargo +nightly fmt --all (CI)
  • cargo +nightly clippy --workspace --release --all-targets -- -D warnings (CI)
  • cargo +nightly test --workspace (CI)
  • Frontend touched: not applicable
  • Tested on an RK3588 device: deployed to the NanoPC-T6, startup check passed (4K60 video plays, no WARN/ERROR at startup). Two-tab take-over test, 12 take-overs: fd count 57 → 60 → 60, socket fds stayed at 22, :80 established connections stayed at 3 (before the fix the same 6 take-overs added +21 fds and sockets reached 70). The +3 are dmabuf video buffers settling and did not grow in the second round. ICE WARN lines (candidate close, mDNS, fe80 listen) appear during repeated setup/teardown; no ERROR, no functional impact seen.

Checklist

  • No #[allow(...)] suppressions and no new unwrap() / expect() in production paths
  • Hot paths stay zero-copy; periodic loops use MissedTickBehavior::Delay
  • Shared protocol types live in rkvm-proto
  • RPC method set changed → not applicable
  • Module tree or build invariants changed → not applicable

Follow-up to #53, which fixed the browser-side WebSocket leak; this is the device-side fd leak found in the same test.

🤖 Generated with Claude Code

https://claude.ai/code/session_01PbdzY6PfT28goR4BhqdsXR

Every taken-over session left about three UDP sockets open on the
device (one ICE host candidate per local address), so rustkvm_app's fd
count grew by ~3.5 per session even though pc.close() was called.

webrtc-util's UdpSocket::close is a no-op; the socket only closes when
its last Arc drops. The on_data_channel handler, which the peer
connection owns, captured a Session clone holding Arc<RTCPeerConnection>,
and DataChannelManager passed that Session on into the data channel
callbacks. The connection therefore owned a reference to itself and was
never dropped, keeping its ICE agent and candidate sockets alive.

Give the handler a Session clone without the peer connection; data
channel routing only uses the id and channels.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Rust-KVM Rust-KVM self-assigned this Oct 11, 2026
@github-actions github-actions Bot added the area: video GStreamer, MPP encoding, WebRTC media label Oct 11, 2026
@Rust-KVM
Rust-KVM merged commit c859659 into dev Oct 11, 2026
8 checks passed
@Rust-KVM
Rust-KVM deleted the claude/webrtc-session-close branch October 12, 2026 13:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: video GStreamer, MPP encoding, WebRTC media

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants