Fix data race on channel_ in RtpTransceiver Capture raw pointer to channel in SetRtpTransportState callback to avoid reading channel_ member on network thread. Unsubscribe on network thread before destruction on worker thread ensures lifetime safety. Caught here: https://chromium-swarm.appspot.com/task?id=77f695c1d91f3911 Bug: webrtc:42224170 Change-Id: I3736870ea6cbc3a7b880d0d6afec2688ea8de7a8 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/468640 Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org> Reviewed-by: Harald Alvestrand <hta@webrtc.org> Cr-Commit-Position: refs/heads/main@{#47586}
diff --git a/pc/rtp_transceiver.cc b/pc/rtp_transceiver.cc index 9554f20..ca6809d 100644 --- a/pc/rtp_transceiver.cc +++ b/pc/rtp_transceiver.cc
@@ -1398,10 +1398,16 @@ RTC_DCHECK(!rtp_transport_); rtp_transport_ = transport; if (rtp_transport_) { + // Safe to capture raw pointer to channel because we unsubscribe on the + // network thread (via GetClearChannelNetworkTask) before the channel is + // destroyed on the worker thread (via GetDeleteChannelWorkerTask). + // Capturing raw pointer avoids reading `channel_` member on the network + // thread, which races with signaling thread moving it during teardown. rtp_transport_->SubscribeNetworkRouteChanged( - this, [this](std::optional<NetworkRoute> route) { + this, + [this, channel = channel_.get()](std::optional<NetworkRoute> route) { RTC_DCHECK_RUN_ON(context()->network_thread()); - OnNetworkRouteChanged(route); + OnNetworkRouteChanged(channel, route); }); } } @@ -1426,11 +1432,12 @@ } void RtpTransceiver::OnNetworkRouteChanged( + ChannelInterface* channel, std::optional<NetworkRoute> network_route) { RTC_DCHECK_RUN_ON(context()->network_thread()); - if (channel_ && rtp_transport_) { - RTC_LOG(LS_INFO) << "Network route changed for mid=" << channel_->mid(); - channel_->media_send_channel()->OnNetworkRouteChanged( + if (channel && rtp_transport_) { + RTC_LOG(LS_INFO) << "Network route changed for mid=" << channel->mid(); + channel->media_send_channel()->OnNetworkRouteChanged( rtp_transport_->transport_name(), network_route.value_or(NetworkRoute())); }
diff --git a/pc/rtp_transceiver.h b/pc/rtp_transceiver.h index 6ffbe33..fe51e86 100644 --- a/pc/rtp_transceiver.h +++ b/pc/rtp_transceiver.h
@@ -450,7 +450,8 @@ RTCErrorOr<std::optional<std::string>> InitializeOnNetworkThread( absl::AnyInvocable<RtpTransportInternal*() &&> transport_lookup) RTC_RUN_ON(context()->network_thread()); - void OnNetworkRouteChanged(std::optional<NetworkRoute> network_route) + void OnNetworkRouteChanged(ChannelInterface* channel, + std::optional<NetworkRoute> network_route) RTC_RUN_ON(context()->network_thread()); void ClearRtpTransportState() RTC_RUN_ON(context()->network_thread()); void SetRtpTransportState(RtpTransportInternal* transport)