Skip to content

Commit 59d83d2

Browse files
authored
Fix race condition during sync (#861)
Resolves #859 Swift SDK uses `isSubscribed` which checks if a track is actually attached, but during reconnection, the `PeerConnection` hasn't fired the `onTrack` event yet, so the track is `nil`, making `isSubscribed = false`. Using JS convention `isDesired` here.
1 parent 9a10a92 commit 59d83d2

File tree

4 files changed

+14
-6
lines changed

4 files changed

+14
-6
lines changed

.changes/sync-race-cond

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
patch type="fixed" "Race condition during sync preventing track subscription"

Sources/LiveKit/Core/Room+Engine.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,9 +448,12 @@ extension Room {
448448
// 2. autosubscribe off, we send subscribed tracks.
449449

450450
let autoSubscribe = _state.connectOptions.autoSubscribe
451+
// Use isDesired (subscription intent) instead of isSubscribed (actual state)
452+
// to avoid race condition during quick reconnect where tracks aren't attached yet.
451453
let trackSids = _state.remoteParticipants.values.flatMap { participant in
452454
participant._state.trackPublications.values
453-
.filter { $0.isSubscribed != autoSubscribe }
455+
.compactMap { $0 as? RemoteTrackPublication }
456+
.filter { $0.isDesired != autoSubscribe }
454457
.map(\.sid)
455458
}
456459

Sources/LiveKit/Track/Capturers/CameraCapturer.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ public class CameraCapturer: VideoCapturer, @unchecked Sendable {
5050
public var isMultitaskingAccessSupported: Bool {
5151
#if (os(iOS) || os(tvOS)) && !targetEnvironment(macCatalyst)
5252
if #available(iOS 16, *, tvOS 17, *) {
53-
self.capturer.captureSession.beginConfiguration()
54-
defer { self.capturer.captureSession.commitConfiguration() }
55-
return self.capturer.captureSession.isMultitaskingCameraAccessSupported
53+
capturer.captureSession.beginConfiguration()
54+
defer { capturer.captureSession.commitConfiguration() }
55+
return capturer.captureSession.isMultitaskingCameraAccessSupported
5656
}
5757
#endif
5858
return false
@@ -62,15 +62,15 @@ public class CameraCapturer: VideoCapturer, @unchecked Sendable {
6262
get {
6363
#if (os(iOS) || os(tvOS)) && !targetEnvironment(macCatalyst)
6464
if #available(iOS 16, *, tvOS 17, *) {
65-
return self.capturer.captureSession.isMultitaskingCameraAccessEnabled
65+
return capturer.captureSession.isMultitaskingCameraAccessEnabled
6666
}
6767
#endif
6868
return false
6969
}
7070
set {
7171
#if (os(iOS) || os(tvOS)) && !targetEnvironment(macCatalyst)
7272
if #available(iOS 16, *, tvOS 17, *) {
73-
self.capturer.captureSession.isMultitaskingCameraAccessEnabled = newValue
73+
capturer.captureSession.isMultitaskingCameraAccessEnabled = newValue
7474
}
7575
#endif
7676
}

Sources/LiveKit/TrackPublications/RemoteTrackPublication.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ public class RemoteTrackPublication: TrackPublication, @unchecked Sendable {
5252
return _state.isSubscribePreferred != false && super.isSubscribed
5353
}
5454

55+
var isDesired: Bool {
56+
_state.isSubscribePreferred != false
57+
}
58+
5559
@objc
5660
public var subscriptionState: SubscriptionState {
5761
if !isSubscriptionAllowed { return .notAllowed }

0 commit comments

Comments
 (0)