Closed piotrtobolski closed 3 years ago
Hi @piotrtobolski!
Thanks for reporting this; however I don't think a sleep is the proper fix here. I'm unable to reproduce locally, however from your triage of the issue, the fix should be that amplitude SDK should stop doing dispatch_sync on the main queue when it is called from the main queue. Or optionally, the amplitude segment integration should call Amplitude.init from a background thread if that is required.
Typically, using a sleep to fix a race condition just pushes said race condition elsewhere.
@bsneed please revise and reopen the issue. I think there is some misunderstanding. This is just issue report, not a solution. Sleep is used to simulate writing to disk taking long time. It isn't used for the fix but to ensure whoever is debugging it has 100% reproduction.
If you check the source changes in attached PR #1009 (It's just 3 lines) you will see that the fix is to ensure that -[SEGIntegrationsManager refreshSettings]
is always called on the same (segment private) queue ensuring that shared resource access is synchronized. This solution isn't moving the race condition elsewhere but removes it completely.
I considered making a fix in Amplitude but I decided it isn't the culprit here. It is calling dispatch_sync with main only when code is executed from non-main queue and it is required to call UIKit methods. Segment SDK is the one that is calling dispatch_sync with private queue from main and blocking it. This PR fixes this. This is result of my investigation. Of course, there may be other solutions (on integrated SDKs side as well) but I think it is still worth implementing this fix because integrating with other SDKs is Segment core feature so it is important to be a good citizen and avoid blocking the main queue.
We still consistently see crashes on first launch of our app 💥 This does not seem to have been resolved
I am using my fork which includes fix for this issue: https://github.com/piotrtobolski/analytics-ios/tree/deadlock-fix It is running in production and I see no crashes about this anymore.
@philipengberg You can add it to cocoapods like this: pod 'Analytics', :git => 'https://github.com/piotrtobolski/analytics-ios.git', :branch => 'deadlock-fix'
I plan to update this branch every few weeks when origin has updates. Point to specific commit hash in podfile if you don't want updates.
Hi @piotrtobolski you're right, I was misunderstanding what you were saying. Really sorry about that.
@bsneed https://github.com/segmentio/analytics-ios/issues/1043 Is this related happening iOS 16? Seeing for few users.
Description
Segment SDK can deadlock on app launch when using some of the integrations. Amplitude integration is one of those and I think it is one of the more popular ones.
The flaw in the integration manager module. It happens when integration initializer calls
dispatch_sync
with main queue. This is the case inside-[Amplitude runSynchronouslyOnMainQueue:]
which is called from-[Amplitude initializeApiKey:userId:setUserId:]
. This situation doesn't happen always because it is related to disk writing latency but in my app on some devices it was happening very often right after installation of the app from TestFlight. Detailed steps below.I will also provide PR fixing this
Prerequisities
Steps
-> main queue
-[SEGIntegrationsManager initWithAnalytics:]
io.segment.analytics
queue->
io.segment.analytics
queue-[SEGIntegrationsManager setCachedSettings:]
-> main queue continues
-[SEGIntegrationsManager onAppForeground:]
-[SEGIntegrationsManager refreshSettings]
-[SEGIntegrationsManager setCachedSettings:]
->
io.segment.analytics
queue continues-[SEGIntegrationsManager updateIntegrationsWithSettings:]
-> main queue
-[SEGIntegrationsManager updateIntegrationsWithSettings:]
io.segment.analytics
queue and waitsFIN: deadlock because both
io.segment.analytics
and main queue are waiting for each otherExample log
[NSThread sleepForTimeInterval:2]
added after writing settings to file