-
Notifications
You must be signed in to change notification settings - Fork 329
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Main Thread Locking #4137
Comments
👀 We've just linked this issue to our internal tracker and notified the team. Thank you for reporting, we're checking this out! |
@tristan-warner-smith thanks for reporting! It does feel related to the bug that @joshdholtz's PR fixes, despite the console output, since we get the storefront through SK1 even if SK2 is enabled |
@aboedo I've tried out @joshdholtz's PR and it did make a difference but unfortunately didn't go far enough. And here's a crash log we got with it: |
Here is a test case that can reliably reproduce this deadlock: func testDeadlock() {
NotificationCenter.default.addObserver(forName: UserDefaults.didChangeNotification,
object: nil,
queue: OperationQueue.main) { _ in }
let userDefaults = SynchronizedUserDefaults(userDefaults: UserDefaults.standard)
DispatchQueue.global(qos: .userInteractive).async { [userDefaults] in
userDefaults.write {
$0.set("value", forKey: "key")
}
}
// Suspend main thread to give the above background write operation time
// to perform and trigger a did change notification on the main queue
Thread.sleep(forTimeInterval: 0.5)
_ = userDefaults.read {
$0.string(forKey: "key")
}
} The deadlock occurs when:
From frame 7, the notification is either:
Generally speaking, it is not a good idea for an object (A) to call another object (B) (like a delegate) or execute a provided block (usuaslly a callback/completion block) while holding its lock. Since A doesn't know nor control what B or the block will do, it essentially exposes its lock to those outsiders and loses control over it. It opens the door for deadlocks like this. To retain control, A should almost always release its lock before calling out. And this is probably what This leads to my main questions: Why do we need After briefly looking at usages of |
Describe the bug
We're experiencing somewhat regular main thread hangs that appear to be related to
lock
usage in the SDK.Attaching images below.
usesStoreKit2IfAvailable(true)
)Purchases.logLevel = .verbose
will help us debug this issue.Swift UI project targeting iOS 16+.
The SDK is configured within the scope of the App's init:
The SDK is initialised in a
Task
of the ViewModel's initialiser. The init is executed on theMainActor
as it's called from the App, so the SDK call toPurchases.configure(withAPIKey: apiKey, appUserID: nil)
will be using that parent scope.Other information (e.g. stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, etc.)
There's what could be related PR open although the console says
"Purchases is configured with StoreKit version 2"
Additional context
Add any other context about the problem here.
The text was updated successfully, but these errors were encountered: