@@ -887,42 +887,47 @@ void WebRTCProviderManager::OnConnectionStateChanged(bool connected, const uint1
887887 }
888888 else
889889 {
890- WebrtcTransport * transport = GetTransport (sessionId);
891- if (transport == nullptr )
892- {
893-
894- ChipLogProgress (Camera,
895- " Transport not found for session %u during disconnect; session may have already been cleaned up" ,
896- sessionId);
897- return ;
898- }
890+ // Schedule cleanup on Matter thread to ensure proper locking when calling RemoveSession.
891+ // Safe to capture 'this' by value: WebRTCProviderManager is a member of the global CameraDevice
892+ // object which has static storage duration and lives for the entire program lifetime.
893+ DeviceLayer::SystemLayer ().ScheduleLambda ([this , sessionId]() {
894+ WebrtcTransport * transport = GetTransport (sessionId);
895+ if (transport == nullptr )
896+ {
897+ ChipLogProgress (Camera,
898+ " Transport not found for session %u during disconnect; session may have already been cleaned up" ,
899+ sessionId);
900+ return ;
901+ }
899902
900- // Connection was closed/disconnected by the peer - clean up the session
901- ChipLogProgress (Camera, " Peer connection closed for session %u, cleaning up resources" , sessionId);
903+ // Connection was closed/disconnected by the peer - clean up the session
904+ ChipLogProgress (Camera, " Peer connection closed for session %u, cleaning up resources" , sessionId);
902905
903- // Release the Video and Audio Streams from the CameraAVStreamManagement
904- // cluster and update the reference counts.
905- ReleaseAudioVideoStreams (sessionId);
906+ // Release the Video and Audio Streams from the CameraAVStreamManagement
907+ // cluster and update the reference counts.
908+ ReleaseAudioVideoStreams (sessionId);
906909
907- // Capture args before unregistering in case the transport is invalidated
908- WebrtcTransport::RequestArgs args = transport->GetRequestArgs ();
910+ // Capture args before unregistering in case the transport is invalidated
911+ WebrtcTransport::RequestArgs args = transport->GetRequestArgs ();
909912
910- // Unregister the transport from the media controller
911- UnregisterWebrtcTransport (sessionId);
913+ // Unregister the transport from the media controller
914+ UnregisterWebrtcTransport (sessionId);
912915
913- // Remove from session maps
914- mSessionIdMap .erase (ScopedNodeId (args.peerNodeId , args.fabricIndex ));
916+ // Remove from session maps
917+ mSessionIdMap .erase (ScopedNodeId (args.peerNodeId , args.fabricIndex ));
915918
916- // Remove from current sessions list in the WebRTC Transport Provider
917- if (mWebRTCTransportProvider != nullptr )
918- {
919- mWebRTCTransportProvider ->RemoveSession (sessionId);
920- }
919+ // Remove from current sessions list in the WebRTC Transport Provider
920+ // This MUST be called on the Matter thread with the stack lock held
921+ if (mWebRTCTransportProvider != nullptr )
922+ {
923+ mWebRTCTransportProvider ->RemoveSession (sessionId);
924+ }
921925
922- // Finally, remove and destroy the transport
923- mWebrtcTransportMap .erase (sessionId);
926+ // Finally, remove and destroy the transport
927+ mWebrtcTransportMap .erase (sessionId);
924928
925- ChipLogProgress (Camera, " Session %u cleanup completed" , sessionId);
929+ ChipLogProgress (Camera, " Session %u cleanup completed" , sessionId);
930+ });
926931 }
927932}
928933
0 commit comments