Bug 313426

Summary: Leak due to retain cycle between LibWebRTCRtp{Sender,Receiver}TransformBackend and libwebrtc sender/receiver after RTCPeerConnection closes
Product: WebKit Reporter: David Kilzer (:ddkilzer) <ddkilzer>
Component: WebRTCAssignee: David Kilzer (:ddkilzer) <ddkilzer>
Status: RESOLVED FIXED    
Severity: Normal CC: webkit-bug-importer, youennf
Priority: P2 Keywords: InRadar
Version: WebKit Nightly Build   
Hardware: Unspecified   
OS: Unspecified   
Bug Depends on: 218750    
Bug Blocks:    

David Kilzer (:ddkilzer)
Reported 2026-04-27 07:01:25 PDT
`WebCore::LibWebRTCRtpSenderTransformBackend` and `WebCore::LibWebRTCRtpReceiverTransformBackend` leak due to retain cycles whenever a page uses an `RTCRtpScriptTransform` or `RTCRtpSFrameTransform` on an `RTCRtpSender` or `RTCRtpReceiver`. The cycle persists after `RTCPeerConnection.close()` and after JavaScript has dropped all references to the sender/receiver, so the leak is permanent for the remaining lifetime of the WebContent process. Each cycle has this structure (shown by `leaks --groupByType` on a memgraph captured from a WebContent process that ran `LayoutTests/http/wpt/webrtc/` tests): ``` 541 (5.61M) ROOT CYCLE: webrtc::RefCountedObject<webrtc::RtpSenderProxyWithInternal<webrtc::RtpSenderInternal>> 528 (5.61M) ROOT CYCLE: webrtc::RefCountedObject<webrtc::AudioRtpSender> 26 (1.83K) ROOT CYCLE: WebCore::LibWebRTCRtpSenderTransformBackend CYCLE BACK TO webrtc::RefCountedObject<webrtc::RtpSenderProxyWithInternal<webrtc::RtpSenderInternal>> 13 (1.22K) ROOT CYCLE: webrtc::RefCountedObject<webrtc::DtmfSender> 13 (624 bytes) ROOT CYCLE: webrtc::RefCountedObject<webrtc::DtmfSenderProxyWithInternal<webrtc::DtmfSenderInterface>> ``` The receiver side has an analogous cycle involving `LibWebRTCRtpReceiverTransformBackend`, `webrtc::AudioRtpReceiver`/`webrtc::VideoRtpReceiver`, and `webrtc::RtpReceiverProxyWithInternal`. Root cause: 1. `LibWebRTCRtpSenderTransformBackend` stores the libwebrtc sender as `const Ref<webrtc::RtpSenderInterface> m_rtcSender;` (strong ref, from backend -> sender). 2. On the first call to `LibWebRTCRtpSenderTransformBackend::setTransformableFrameCallback()`, the backend registers itself with the sender via `m_rtcSender->SetFrameTransformer(scoped_refptr<FrameTransformerInterface>(this))`. libwebrtc stores this in `RtpSenderBase::frame_transformer_`, a `scoped_refptr<FrameTransformerInterface>` (strong ref, from sender -> backend). 3. Both sides hold strong refs, so neither drops first. The cycle keeps both objects alive indefinitely. `LibWebRTCRtpReceiverTransformBackend` has the same two-way relationship with its `webrtc::RtpReceiverInterface` via `SetFrameTransformer()` in `setTransformableFrameCallback()`. Reproduction: Run any WebRTC layout test that attaches a transform to a sender or receiver (for example `http/wpt/webrtc/unset-transform.html`, `http/wpt/webrtc/audiovideo-script-transform.html`, `webrtc/sframe-keys.html`, or `webrtc/video-sframe.html`) with `run-webkit-tests --debug --leaks`. `leaks --groupByType` on the resulting WebContent memgraph reports multiple `ROOT CYCLE` entries naming `WebCore::LibWebRTCRtpSenderTransformBackend` or `WebCore::LibWebRTCRtpReceiverTransformBackend`. The cycle has existed since WebRTC transform infrastructure was introduced in Bug 218750, 231538@main (2020-11-13).
Attachments
Radar WebKit Bug Importer
Comment 1 2026-04-27 07:01:35 PDT
David Kilzer (:ddkilzer)
Comment 2 2026-04-27 07:46:22 PDT
EWS
Comment 3 2026-04-27 22:42:20 PDT
Committed 312177@main (0f476dfaa434): <https://commits.webkit.org/312177@main> Reviewed commits have been landed. Closing PR #63695 and removing active labels.
Note You need to log in before you can comment on or make changes to this bug.