Skip to content

Purchases framework causes crash on older iOS devices #278

Description

@kbunarjo

Describe the bug
We had recently updated this framework from 2.0.1 to version 4.14.1. However, we've started getting crashes on older iOS devices. The crash happens right after our splash screen is finished displaying -- right when our first scene is loaded in. The stack trace for this issue is here:

Date/Time:           2023-04-26 21:45:28.2987 -0500
Launch Time:         2023-04-26 21:45:15.3798 -0500
OS Version:          iPhone OS 12.5.7 (16H81)
Baseband Version:    10.80.02
Report Version:      104

Exception Type:  EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note:  EXC_CORPSE_NOTIFY
Triggered by Thread:  0

Thread 0 name:
Thread 0 Crashed:
0   dyld                          	0x00000001001ae418 __abort_with_payload + 8
1   dyld                          	0x00000001001ada58 abort_with_payload_wrapper_internal + 100 (terminate_with_reason.c:72)
2   dyld                          	0x00000001001ada88 abort_with_payload + 12 (terminate_with_reason.c:94)
3   dyld                          	0x00000001001708f8 dyld::halt(char const*) + 304 (dyld.cpp:4024)
4   dyld                          	0x0000000100170a14 dyld::fastBindLazySymbol(ImageLoader**, unsigned long) + 284 (dyld.cpp:4112)
5   libdyld.dylib                 	0x00000001d7353848 dyld_stub_binder + 60
6   UnityFramework                	0x0000000102346a38 type metadata completion function for SK2StoreProduct + 24 (<compiler-generated>:0)
7   libswiftCore.dylib            	0x0000000205128820 swift_getSingletonMetadata + 636 (MetadataCache.h:920)
8   UnityFramework                	0x0000000102346a18 type metadata accessor for SK2StoreProduct + 48 (<compiler-generated>:0)
9   libswiftCore.dylib            	0x000000020513f098 swift_conformsToSwiftProtocolImpl(swift::TargetMetadata<swift::InProcess> const*, swift::TargetProtocolDescriptor<swift::InProcess> const*, llvm::StringRef) + 312 (ProtocolConformance.cpp:478)
10  libswiftCore.dylib            	0x000000020513ee38 swift_conformsToProtocol + 188 (CompatibilityOverride.def:137)
11  libswiftCore.dylib            	0x0000000205118a58 swift::_conformsToProtocol(swift::OpaqueValue const*, swift::TargetMetadata<swift::InProcess> const*, swift::TargetProtocolDescriptorRef<swift::InProcess>, swift::TargetWitnessTable<swift::InProces... + 44 (Casting.cpp:320)
12  libswiftCore.dylib            	0x000000020513e6fc swift::_checkGenericRequirements(llvm::ArrayRef<swift::TargetGenericRequirementDescriptor<swift::InProcess> >, std::__1::vector<void const*, std::__1::allocator<void const*> >&, std::__1::function<... + 1160 (ProtocolConformance.cpp:648)
13  libswiftCore.dylib            	0x000000020513b740 (anonymous namespace)::DecodedMetadataBuilder::createBoundGenericType(swift::TargetContextDescriptor<swift::InProcess> const*, llvm::ArrayRef<swift::TargetMetadata<swift::InProcess> const*>, swift:... + 584 (MetadataLookup.cpp:1083)
14  libswiftCore.dylib            	0x000000020513adec swift::Demangle::TypeDecoder<(anonymous namespace)::DecodedMetadataBuilder>::decodeMangledType(swift::Demangle::Node* const&) + 2832 (TypeDecoder.h:201)
15  libswiftCore.dylib            	0x000000020513a428 swift::Demangle::TypeDecoder<(anonymous namespace)::DecodedMetadataBuilder>::decodeMangledType(swift::Demangle::Node* const&) + 332 (Demangle.h:0)
16  libswiftCore.dylib            	0x0000000205139d10 swift_getTypeByMangledNodeImpl(swift::MetadataRequest, swift::Demangle::Demangler&, swift::Demangle::Node*, std::__1::function<swift::TargetMetadata<swift::InProcess> const* (unsigned int, unsigned... + 460 (TypeDecoder.h:700)
17  libswiftCore.dylib            	0x0000000205139ad0 swift::swift_getTypeByMangledNode(swift::MetadataRequest, swift::Demangle::Demangler&, swift::Demangle::Node*, std::__1::function<swift::TargetMetadata<swift::InProcess> const* (unsigned int, unsig... + 520 (CompatibilityOverride.def:148)
18  libswiftCore.dylib            	0x000000020513a044 swift_getTypeByMangledNameImpl(swift::MetadataRequest, llvm::StringRef, std::__1::function<swift::TargetMetadata<swift::InProcess> const* (unsigned int, unsigned int)>, std::__1::function<swift::Ta... + 652 (MetadataLookup.cpp:1300)
19  libswiftCore.dylib            	0x0000000205138450 swift::swift_getTypeByMangledName(swift::MetadataRequest, llvm::StringRef, std::__1::function<swift::TargetMetadata<swift::InProcess> const* (unsigned int, unsigned int)>, std::__1::function<swift:... + 520 (CompatibilityOverride.def:155)
20  libswiftCore.dylib            	0x000000020513859c swift_getTypeByMangledNameInContext + 216 (MetadataLookup.cpp:1326)
21  UnityFramework                	0x0000000102112694 __swift_instantiateConcreteTypeFromMangledName + 52 (<compiler-generated>:0)
22  UnityFramework                	0x00000001022d14d0 specialized _NativeDictionary.resize(capacity:) + 12 (<compiler-generated>:0)
23  UnityFramework                	0x00000001022d14d0 specialized _NativeDictionary.ensureUnique(isUnique:capacity:) + 24 (<compiler-generated>:0)
24  UnityFramework                	0x00000001022d14d0 specialized _NativeDictionary.mutatingFind(_:isUnique:) + 64 (<compiler-generated>:0)
25  UnityFramework                	0x00000001022d14d0 specialized _NativeDictionary.merge<A>(_:isUnique:uniquingKeysWith:) + 196
26  UnityFramework                	0x00000001022d1368 specialized protocol witness for Sequence.underestimatedCount.getter in conformance LazyMapSequence<A, B> + 32 (<compiler-generated>:0)
27  UnityFramework                	0x00000001022d1368 specialized Dictionary.init<A>(uniqueKeysWithValues:) + 32 (Logger.swift:267)
28  UnityFramework                	0x00000001022d1368 one-time initialization function for order + 108
29  libdispatch.dylib             	0x00000001d73407d4 _dispatch_client_callout + 16 (object.m:511)
30  libdispatch.dylib             	0x00000001d72e3eb8 _dispatch_once_callout + 28 (once.c:52)
31  libswiftCore.dylib            	0x000000020513de40 swift_once + 40 (once.h:111)
32  UnityFramework                	0x00000001022da794 specialized static Logger.log(level:intent:message:fileName:functionName:line:) + 700
33  UnityFramework                	0x00000001022d9888 specialized static Logger.log(level:intent:message:fileName:functionName:line:) + 64
34  UnityFramework                	0x000000010231b630 specialized static Logger.log(level:intent:message:fileName:functionName:line:) + 60 (Logger.swift:127)
35  UnityFramework                	0x000000010231b630 static Logger.debug(_:fileName:functionName:line:) + 60 (Purchases.swift:0)
36  UnityFramework                	0x000000010231b630 specialized Purchases.__allocating_init(apiKey:appUserID:userDefaults:observerMode:platformInfo:responseVerificationLevel:storeKit2Setting:storeKitTimeout:networkTimeout:dangerousSettings:) + 172
37  UnityFramework                	0x000000010231dd0c Purchases.__allocating_init(apiKey:appUserID:userDefaults:observerMode:platformInfo:responseVerificationLevel:storeKit2Setting:storeKitTimeout:networkTimeout:dangerousSettings:) + 52 (<compiler-generated>:1038)
38  UnityFramework                	0x000000010231dd0c implicit closure #1 in static Purchases.configure(withAPIKey:appUserID:observerMode:userDefaults:platformInfo:responseVerificationLevel:storeKit2Setting:storeKitTimeout:networkTimeout:dangerousSett... + 104 (<compiler-generated>:0)
39  UnityFramework                	0x000000010231dd0c partial apply for implicit closure #1 in static Purchases.configure(withAPIKey:appUserID:observerMode:userDefaults:platformInfo:responseVerificationLevel:storeKit2Setting:storeKitTimeout:networkTim... + 172
40  UnityFramework                	0x00000001023191d4 closure #1 in static Purchases.setDefaultInstance(_:) + 4 (Purchases.swift:517)
41  UnityFramework                	0x00000001023191d4 specialized closure #1 in Atomic.modify<A>(_:) + 4 (Atomic.swift:64)
42  UnityFramework                	0x00000001023191d4 specialized closure #1 in Atomic.modify<A>(_:) + 4 (<compiler-generated>:0)
43  UnityFramework                	0x00000001023191d4 specialized Lock.perform<A>(_:) + 4 (Lock.swift:49)
44  UnityFramework                	0x00000001023191d4 specialized Atomic.modify<A>(_:) + 4 (Atomic.swift:63)
45  UnityFramework                	0x00000001023191d4 specialized static Purchases.setDefaultInstance(_:) + 192 (Purchases.swift:504)
46  UnityFramework                	0x000000010231d340 static Purchases.setDefaultInstance(_:) + 16 (<compiler-generated>:0)
47  UnityFramework                	0x000000010231d340 static Purchases.configure(withAPIKey:appUserID:observerMode:userDefaults:platformInfo:responseVerificationLevel:storeKit2Setting:storeKitTimeout:networkTimeout:dangerousSettings:) + 48 (Purchases.swift:909)
48  UnityFramework                	0x000000010231d340 specialized static Purchases.configure(with:) + 224
49  UnityFramework                	0x0000000102248750 static Purchases.configure(apiKey:appUserID:observerMode:userDefaultsSuiteName:platformFlavor:platformFlavorVersion:usesStoreKit2IfAvailable:dangerousSettings:) + 880 (Purchases+HybridAdditions.swift:49)
50  UnityFramework                	0x0000000102248914 @objc static Purchases.configure(apiKey:appUserID:observerMode:userDefaultsSuiteName:platformFlavor:platformFlavorVersion:usesStoreKit2IfAvailable:dangerousSettings:) + 304 (<compiler-generated>:0)
51  UnityFramework                	0x00000001020fae2c -[RCUnityHelperDelegate setupPurchases:appUserID:gameObject:observerMode:usesStoreKit2IfAvailable:userDefaultsSuiteName:dangerousSettingsJson:] + 448 (PurchasesUnityHelper.m:83)
52  UnityFramework                	0x00000001020fc22c _RCSetupPurchases + 208 (PurchasesUnityHelper.m:454)
53  UnityFramework                	0x0000000104bb2c00 PurchasesWrapperiOS__RCSetupPurchases_mD3D94F7356E6ACB5DC9D4144B05271890B674AC9 + 136 (revenuecat.purchases-unity.cpp:12676)
54  UnityFramework                	0x0000000104ba6b14 InterfaceActionInvoker8<String_t*, String_t*, String_t*, bool, bool, String_t*, bool, String_t*>::Invoke(unsigned short, Il2CppClass*, Il2CppObject*, String_t*, String_t*, String_t*, bool, bool, St... + 32 (revenuecat.purchases-unity.cpp:186)
55  UnityFramework                	0x0000000104ba6b14 Purchases_Configure_mB6B15274DFB7B7FFCB1D96E626D7C6DE2A9A3FF0 + 304 (revenuecat.purchases-unity.cpp:4534)
56  UnityFramework                	0x0000000104ba63d8 Purchases_Start_m879CBCF4317AB1B0233FBD048C48D5B99E5C382B + 316 (revenuecat.purchases-unity.cpp:4297)
57  UnityFramework                	0x00000001030975f8 il2cpp::vm::Runtime::InvokeWithThrow(MethodInfo const*, void*, void**) + 100 (Runtime.cpp:567)
58  UnityFramework                	0x0000000103097458 il2cpp::vm::Runtime::Invoke(MethodInfo const*, void*, void**, Il2CppException**) + 84 (Runtime.cpp:553)
59  UnityFramework                	0x00000001025e2094 scripting_method_invoke(ScriptingMethodPtr, ScriptingObjectPtr, ScriptingArguments&, ScriptingExceptionPtr*, bool) + 112 (ScriptingApi_Il2Cpp.cpp:292)
60  UnityFramework                	0x00000001025ede3c ScriptingInvocation::Invoke(ScriptingExceptionPtr*, bool) + 120 (ScriptingInvocation.cpp:298)
61  UnityFramework                	0x00000001025fdf14 MonoBehaviour::InvokeMethodOrCoroutineChecked(ScriptingMethodPtr, ScriptingObjectPtr, ScriptingExceptionPtr*) + 2012 (MonoBehaviour.cpp:0)
62  UnityFramework                	0x00000001025fe098 MonoBehaviour::InvokeMethodOrCoroutineChecked(ScriptingMethodPtr, ScriptingObjectPtr) + 84 (MonoBehaviour.cpp:860)
63  UnityFramework                	0x00000001025fe880 Start + 40 (MonoBehaviour.cpp:465)
64  UnityFramework                	0x00000001025fe880 MonoBehaviour::DelayedStartCall(Object*, void*) + 56 (MonoBehaviour.cpp:1239)
65  UnityFramework                	0x0000000102448f54 DelayedCallManager::Update(int) + 536 (CallDelayed.cpp:185)
66  UnityFramework                	0x000000010250b34c ExecutePlayerLoop(NativePlayerLoopSystem*) + 100 (PlayerLoop.cpp:383)
67  UnityFramework                	0x000000010250b38c ExecutePlayerLoop(NativePlayerLoopSystem*) + 164 (PlayerLoop.cpp:404)
68  UnityFramework                	0x000000010250b5e8 PlayerLoop() + 272 (PlayerLoop.cpp:508)
69  UnityFramework                	0x0000000102af5fc4 UnityPlayerLoopImpl(bool) + 112 (LibEntryPoint.mm:327)
70  UnityFramework                	0x0000000101ebfdb4 UnityRepaint + 12 (UnityAppController+Rendering.mm:236)
71  UnityFramework                	0x0000000101ebfdb4 -[UnityAppController(Rendering) repaint] + 84 (UnityAppController+Rendering.mm:90)
72  UnityFramework                	0x0000000101ebfd44 -[UnityAppController(Rendering) repaintDisplayLink] + 76 (UnityAppController+Rendering.mm:71)
73  QuartzCore                    	0x00000001dbd13ff0 CA::Display::DisplayLink::dispatch_items(unsigned long long, unsigned long long, unsigned long long) + 636 (CADisplay.mm:2349)
74  IOKit                         	0x00000001d7b5f4b0 IODispatchCalloutFromCFMessage + 488 (IOKitLib.c:1216)
75  CoreFoundation                	0x00000001d786d990 __CFMachPortPerform + 188 (CFMachPort.c:522)
76  CoreFoundation                	0x00000001d7894594 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 56 (CFRunLoop.c:1996)
77  CoreFoundation                	0x00000001d7893ce0 __CFRunLoopDoSource1 + 440 (CFRunLoop.c:2133)
78  CoreFoundation                	0x00000001d788eb04 __CFRunLoopRun + 2096 (CFRunLoop.c:3152)
79  CoreFoundation                	0x00000001d788dfb4 CFRunLoopRunSpecific + 436 (CFRunLoop.c:3247)
80  GraphicsServices              	0x00000001d9a9079c GSEventRunModal + 104 (GSEvent.c:2245)
81  UIKitCore                     	0x0000000203d56c38 UIApplicationMain + 212 (UIApplication.m:4353)
82  UnityFramework                	0x0000000101ebf8ec -[UnityFramework runUIApplicationMainWithArgc:argv:] + 92 (main.mm:96)
83  JoonPetGame                   	0x00000001000bb978 main + 744 (main.mm:34)
84  libdyld.dylib                 	0x00000001d73518e0 start + 4

Here's a Sentry error of what's happening:
Screenshot 2023-04-28 at 11 59 55 AM

Do not remove any of the steps from the template below. If a step is not applicable to your issue, please leave that step empty.

  1. Environment
    1. Platform: Unity iOS
    2. SDK version: v4.14.1
    3. OS + version: iOS v12.5.7
    4. Xcode/Android Studio version: Xcode 13 and Xcode 14 (tried both)
    5. Unity version: 2021.3.16f1
    6. How widespread is the issue. Percentage of devices affected. Just affecting users with old iOS devices. About 5
  2. Debug logs that reproduce the issue
  3. Steps to reproduce, with a description of expected vs. actual behavior
  4. Other information (e.g. stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, etc.)

Additional context
Here is our UpdatedCustomerInfoListener class:

using System.Collections.Generic;
using UnityEngine;

// TODO: Since the parent class is not utilized in anyway. I figured it would be safe to just make this a standard
// TODO: Singleton. If there are any issues, I can happily revert it.
public class SubscriptionManager : Purchases.UpdatedCustomerInfoListener
{
    public static SubscriptionManager Instance;
    
    public delegate void SubscriptionStatusCallback(bool isSubscribed, bool isInTrialMode);

    private Purchases Purchases => transform.parent.GetComponentInChildren<Purchases>();

    public void UserLoggedIn(Parent parent)
    {
        // TODO: Created and error are never used. Should we make a use case for them or remove them?
        Purchases.LogIn(appUserId: $"{parent.FamilyId}", callback: (info, _, _) =>
        {
            Purchases.SetEmail(email: parent.Email);
            Purchases.SetAttributes(attributes: new Dictionary<string, string>
            {
                { JoonConsts.PARENT_ID, $"{parent.Id}" },
                { JoonConsts.NAME, parent.Name },
                { JoonConsts.EMAIL, parent.Email }
            });
        });
    }

    public void UserLoggedOut()
    {
        Purchases.LogOut(callback: null);
    }

    public void SubscriptionStatus(SubscriptionStatusCallback callback)
    {
        // Purchases will only return a callback if it actually is on Android or iOS. This check allows us to
        // callback the caller of this function when running on Unity.
        if (Application.platform is RuntimePlatform.Android or RuntimePlatform.IPhonePlayer)
        {
            Purchases.GetCustomerInfo(callback: (info, error) =>
            {
                if (error != null)
                {
                    callback(isSubscribed: false, isInTrialMode: false);
                    return;
                }

                bool isUserSubscribed = info.Entitlements.Active.Count > 0;
                Parent parent = AuthenticationManager.GetParent();
                bool isInTrialMode = parent.NumQuestsVerified < parent.MaxFreeVerified;
                callback(isUserSubscribed, isInTrialMode);
            });
        }
        else
        {
            // Default callback if it isn't iOS or Android.
            callback(true, true);
        }
    }

    // Old Singleton set up for now since this uses an inherited class.
    private void Awake()
    {
        if (Instance != null && Instance != this)
        {
            Destroy(transform.root.gameObject);
        }
        else
        {
            Instance = this;
            DontDestroyOnLoad(transform.root.gameObject);
        }
    }

    // No-op
    public override void CustomerInfoReceived(Purchases.CustomerInfo customerInfo) { }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingtriaged

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions