@@ -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