RevenueCat / purchases-ios

In-app purchases and subscriptions made easy. Support for iOS, watchOS, tvOS, macOS, and visionOS.
https://www.revenuecat.com/
MIT License
2.37k stars 319 forks source link

Main Thread Locking #4137

Open tristan-warner-smith opened 3 months ago

tristan-warner-smith commented 3 months ago

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.

  1. Environment
    1. Platform: iOS
    2. SDK version: 5.2.2
    3. StoreKit version:
      • [x] StoreKit 1
      • [ ] StoreKit 2 (enabled with usesStoreKit2IfAvailable(true))
    4. OS version: 17.5
    5. Xcode version: 15.4
    6. Device and/or simulator:
      • [ ] Device
      • [x] Simulator
    7. Environment:
      • [x] Sandbox
      • [ ] TestFlight
      • [ ] Production
    8. How widespread is the issue. Percentage of devices affected. ~20% of app runs.
  2. Debug logs that reproduce the issue. Complete logs with Purchases.logLevel = .verbose will help us debug this issue.
VERBOSE: DeviceCache.init: DeviceCache (0x0000000117e35570)
VERBOSE: Initializing PaywallEventStore: file:///Users/.../Library/Developer/CoreSimulator/Devices/93F00F5D-1682-4CFA-A69B-81B6FFBEBE4D/data/Containers/Data/Application/96049B6C-F3ED-4A2D-B691-346709938D30/Library/Application%20Support/revenuecat/paywall_event_store
VERBOSE: Creating FileHandler for: file:///Users/.../Library/Developer/CoreSimulator/Devices/93F00F5D-1682-4CFA-A69B-81B6FFBEBE4D/data/Containers/Data/Application/96049B6C-F3ED-4A2D-B691-346709938D30/Library/Application%20Support/revenuecat/paywall_event_store
VERBOSE: PaywallEventsManager initialized
VERBOSE: PurchasesOrchestrator.init: PurchasesOrchestrator (0x0000000118da4b80)
VERBOSE: Purchases.init: created new Purchases instance: Purchases (0x0000000117d06840)
StoreKit Wrapper: right(<RevenueCat.PaymentQueueWrapper: 0x116444590>)
VERBOSE: Updating all caches
VERBOSE: Enqueing network operation 'GetOfferingsOperation' with cache key: 'GetOfferingsOperation a63afqRdLahuvUoUmxgMrsAEOSm2'
VERBOSE: Enqueing network operation 'GetCustomerInfoOperation' with cache key: 'GetCustomerInfoOperation a63afqRdLahuvUoUmxgMrsAEOSm2'
VERBOSE: Using etag 'c237e42911476e3c' for request to 'https://api.revenuecat.com/v1/subscribers/a63afqRdLahuvUoUmxgMrsAEOSm2/offerings'. Validation time: 2024-07-30 20:55:14 +0000
VERBOSE: Storing etag 'c237e42911476e3c' for request to 'https://api.revenuecat.com/v1/subscribers/a63afqRdLahuvUoUmxgMrsAEOSm2/offerings' (success)
VERBOSE: Using etag '1d31eb8debb9281a' for request to 'https://api.revenuecat.com/v1/subscribers/a63afqRdLahuvUoUmxgMrsAEOSm2'. Validation time: 2024-07-30 20:55:12 +0000
VERBOSE: Storing etag '1d31eb8debb9281a' for request to 'https://api.revenuecat.com/v1/subscribers/a63afqRdLahuvUoUmxgMrsAEOSm2' (success)
  1. Steps to reproduce, with a description of expected vs. actual behavior Swift UI project targeting iOS 16+. The SDK is configured within the scope of the App's init:

    @main
    struct App {
    init() {
        self._viewModel = StateObject(wrappedValue: AppViewModel(appRouter: router))
    }
    }

    The SDK is initialised in a Task of the ViewModel's initialiser. The init is executed on the MainActor as it's called from the App, so the SDK call to Purchases.configure(withAPIKey: apiKey, appUserID: nil) will be using that parent scope.

  2. 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" Threads-1 Threads-2

  3. Additional context Add any other context about the problem here.

RCGitBot commented 3 months ago

👀 We've just linked this issue to our internal tracker and notified the team. Thank you for reporting, we're checking this out!

aboedo commented 3 months ago

@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

tristan-warner-smith commented 3 months ago

@aboedo I've tried out @joshdholtz's PR and it did make a difference but unfortunately didn't go far enough. Here's where it's locking subsequently: Screenshot 2024-07-31 at 13 52 59

And here's a crash log we got with it: crashlog.txt

jesus-mg-ios commented 4 days ago

Reproduced ... seems that there's a lock in synchronizedUserDefaults because it uses any kinda lock there and write waits for a read. @aboedo @nyeu any fix ETA?