Skip to content

Commit 5e22f37

Browse files
authored
Fix crash due to race condition when initiating AuthenticatedDotcomRequest (#16259)
2 parents 9651db5 + 91a7435 commit 5e22f37

File tree

1 file changed

+25
-10
lines changed

1 file changed

+25
-10
lines changed

WooCommerce/Classes/System/SessionManager.swift

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ final class SessionManager: SessionManagerProtocol {
5454
///
5555
private let imageCache: ImageCache
5656

57+
/// Serial queue for thread-safe credentials access
58+
///
59+
private let credentialsQueue = DispatchQueue(label: "com.woocommerce.session.credentials", qos: .userInitiated)
60+
5761
/// Makes sure the credentials are in sync with the watch session.
5862
///
5963
private lazy var watchDependenciesSynchronizer = {
@@ -76,20 +80,31 @@ final class SessionManager: SessionManagerProtocol {
7680
///
7781
var defaultCredentials: Credentials? {
7882
get {
79-
return loadCredentials()
83+
credentialsQueue.sync {
84+
loadCredentials()
85+
}
8086
}
8187
set {
82-
guard newValue != defaultCredentials else {
83-
return
84-
}
88+
let shouldUpdateWatchSync = credentialsQueue.sync { () -> Bool in
89+
let currentCredentials = loadCredentials()
90+
guard newValue != currentCredentials else {
91+
return false
92+
}
8593

86-
removeCredentials()
94+
removeCredentials()
8795

88-
if let credentials = newValue {
89-
saveCredentials(credentials)
96+
if let credentials = newValue {
97+
saveCredentials(credentials)
98+
}
99+
100+
return true
90101
}
91102

92-
watchDependenciesSynchronizer.credentials = newValue
103+
// Update watch synchronizer outside the sync block to avoid potential deadlocks
104+
// from @Published property triggering Combine subscribers that might read credentials
105+
if shouldUpdateWatchSync {
106+
watchDependenciesSynchronizer.credentials = newValue
107+
}
93108
}
94109
}
95110

@@ -235,7 +250,7 @@ final class SessionManager: SessionManagerProtocol {
235250
/// Deletes application password
236251
///
237252
func deleteApplicationPassword(using creds: Credentials?, locally: Bool) {
238-
let useCase: ApplicationPasswordUseCase? = {
253+
let useCase: ApplicationPasswordUseCase? = credentialsQueue.sync {
239254
let credentials = creds ?? loadCredentials()
240255
switch credentials {
241256
case let .wporg(username, password, siteAddress):
@@ -253,7 +268,7 @@ final class SessionManager: SessionManagerProtocol {
253268
case .none:
254269
return nil
255270
}
256-
}()
271+
}
257272
guard let useCase else {
258273
return
259274
}

0 commit comments

Comments
 (0)