From 37da5557e944e8230cccc06db28bfe32bbdb468a Mon Sep 17 00:00:00 2001 From: Mathijs Kadijk Date: Fri, 6 Dec 2024 10:13:35 +0100 Subject: [PATCH] Avoid deadlock by moving saveIdentity to read lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the UserDefaults calls made by saveIdentity cause blocking NSNotifications to be emitted to the main thread, calling saveIdentity under the write lock can cause deadlocks. Since the saveIdentity call only reads state it’s now moved to only take a read lock instead of being under the write lock. --- Sources/MixpanelInstance.swift | 10 +++++++++- Sources/ReadWriteLock.swift | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Sources/MixpanelInstance.swift b/Sources/MixpanelInstance.swift index bda85a8f..ea0dcae0 100644 --- a/Sources/MixpanelInstance.swift +++ b/Sources/MixpanelInstance.swift @@ -909,7 +909,7 @@ extension MixpanelInstance { } func unarchive() { - self.readWriteLock.write { + let didCreateIdentity = self.readWriteLock.write { optOutStatus = MixpanelPersistence.loadOptOutStatusFlag(instanceName: self.name) superProperties = MixpanelPersistence.loadSuperProperties(instanceName: self.name) timedEvents = MixpanelPersistence.loadTimedEvents(instanceName: self.name) @@ -927,6 +927,14 @@ extension MixpanelInstance { distinctId = addPrefixToDeviceId(deviceId: anonymousId) hadPersistedDistinctId = true userId = nil + return true + } else { + return false + } + } + + if didCreateIdentity { + self.readWriteLock.read { MixpanelPersistence.saveIdentity(MixpanelIdentity.init( distinctID: distinctId, peopleDistinctID: people.distinctId, diff --git a/Sources/ReadWriteLock.swift b/Sources/ReadWriteLock.swift index f910ebbf..95f65b3c 100644 --- a/Sources/ReadWriteLock.swift +++ b/Sources/ReadWriteLock.swift @@ -19,7 +19,7 @@ class ReadWriteLock { closure() } } - func write(closure: () -> Void) { + func write(closure: () -> T) -> T { concurrentQueue.sync(flags: .barrier, execute: { closure() })