Closed Svantulden closed 2 years ago
How do you integrate the SDK please? CocoaPods? Carthage? Manually? Do you have any changes in the SDK? How you compile it?
I just tried to debug this code path on iOS 15 and the stack trace looks different. The [PFObject init]
actually correctly goes into [PFInstallation(Private) _assertValidInstanceClassName:]
, and that method does not check (correctly) for underscore.
In your case on iOS 13 the code here: https://github.com/parse-community/Parse-SDK-iOS-OSX/blob/e09104ee362ee1a98cf684336097d8f5701031ab/Parse/Parse/PFObject.m#L1673 actually ends up in generic [PFObject _assertValidInstanceClassName:]
and fails because _Installation
has an underscore. Looks super weird.
Just tried to debug this again under simulator running iOS 13.0 and iOS 13.7 and it behaves correctly. Not sure if you can achieve the same (for example by including Parse iOS SDK as a Xcode subproject) and try to debug/reproduce this on your machine on any iOS 13 device.
The breakpoint line is here: https://github.com/parse-community/Parse-SDK-iOS-OSX/blob/e09104ee362ee1a98cf684336097d8f5701031ab/Parse/Parse/PFObject.m#L1673
Thanks for your quick reply!
How do you integrate the SDK please? CocoaPods? Carthage? Manually? Do you have any changes in the SDK? How you compile it?
We are using Carthage with --use-xcframeworks
on an XCode 13 command-line tools version. No custom changes in the SDK, just the 1.19.2 version. Previously (before updating to XCode 13 / iOS 15 stack) we also used Carthage, without --use-xcframeworks
.
actually ends up in generic [PFObject _assertValidInstanceClassName:] and fails because _Installation has an underscore. Looks super weird.
Nice find. Strange indeed. Do you know any ways for it to end up using the installation as a class name? I'm yet too unfamiliar with the SDK code to see how this could end up there. Especially that it seems to only happen on iOS 13.
Just tried to debug this again under simulator running iOS 13.0 and iOS 13.7 and it behaves correctly. Not sure if you can achieve the same (for example by including Parse iOS SDK as a Xcode subproject) and try to debug/reproduce this on your machine on any iOS 13 device.
Will try to find a fosselized iOS device with iOS 13 or a way to install iOS 13 on a testdevice when they aren't signed anymore (I think jailbreaking is the only way? 👀).
You can quickly try to debug it via Xcode Simulator running iOS 13. Download the iOS 13.0 simulator images via Xcode preferences / components window and just run your app against random iOS 13 simulator.
The PFInstallation.currentInstallation
will be called at some point in a lifecycle of your app, and this can give you an idea whether you can actually crash the app in DEBUG builds running against iOS Simulator 13.0. Since you are using Carthage, the SDK will actually be built in release mode, the same way as in your shipping app.
This can help you pinpoint the crash, whether it occurs because of your code, or because of Parse SDK code and the way it is built using Carthage.
You can quickly try to debug it via Xcode Simulator running iOS 13. Download the iOS 13.0 simulator images via Xcode preferences / components window and just run your app against random iOS 13 simulator.
Ah, I thought you meant a physical device specifically, as we cannot reproduce the crash in an iOS 13 simulator while debugging yet.
The PFInstallation.currentInstallation will be called at some point in a lifecycle of your app, and this can give you an idea whether you can actually crash the app in DEBUG builds running against iOS Simulator 13.0. Since you are using Carthage, the SDK will actually be built in release mode, the same way as in your shipping app.
This can help you pinpoint the crash, whether it occurs because of your code, or because of Parse SDK code and the way it is built using Carthage.
Good idea. I've tried this (checking out the 1.19.2 project and adding it as a sub-project for my app), but I'm seeing the same stack trace as you do when setting a breakpoint on _assertValidInstanceClassName
of PFInstallation
. The one on PFObject
itself doesn't get hit.
I've also tried logging in and doing some Parse-related behaviour in my app, like changing the user properties and doing a few commands/calls to the Parse backend, but the only way _assertValidInstanceClassName
gets hit is at startup and only for PFInstallation
as you are also seeing.
We are using PFUser
in our app and [PFUser _assertValidInstanceClassName]
does (also) get hit, so maybe that can provide a hint of some sort?
I am not that familiar with the internals, but from pure deduction, each implementation of PFSubclassing
protocol (or PFObject
) subclass calls _assertValidInstanceClassName
during its creation.
The default implementation (in PFObject
) checks whether the class name does not start with underscore. Not sure why, I assume underscored class names and mongo collections are reserved for internal parse classes (_User
, _Installation
, etc.). And that is why each Parse internal subclass like PFInstallation
, PFUser
, etc... override and customize the _assertValidInstanceClassName
check.
In your case, instead of calling overriden method for PFInstallation
, your code ends up in default implementation of PFObject
...
And because it works mostly, but fails randomly on some versions of iOS, it could be pointing towards a bug in the compiler combined with a bug in the runtime. I know it is a huge speculation.
Could you examine how many iOS 13 variants are actually affected? Do you have any iOS 13 variants where the bug does not happen?
Super weird bug, but I think not in parse code per se, more likely in the way it is integrated in your app and how it is built.
And because it works mostly, but fails randomly on some versions of iOS, it could be pointing towards a bug in the compiler combined with a bug in the runtime. I know it is a huge speculation.
Agreed that it's a huge speculation, but this issue only occurring on iOS 13 versions seems so strange to me.
Thanks for the extra explanation. I've experimented some with those different breakpoints in the different _assertValidInstanceClassName
versions. When a user is logged in within our app, the PFUser
variant of _assertValidInstanceClassName
gets hit together of the one in PFInstallation
. When logged out, only the PFInstallation
one gets hit.
Maybe the PFUser
somehow gets a different [self class]
working in those affected cases, where it hits the PFObject
superclass instead of the PFUser
variant 🤔. Though that wouldn't make sense if the affected users cannot fix the issue by reinstalling the app, as they would then be logged out.
I've compared our Flurry tracking data for iOS 13 versions & app versions that do and do not have iOS 15 support. I'm seeing a relatively small amount of users still being able to use the app properly. It's hard to compare accurately between crashing & non-crashing users, as Flurry doesn't always initialise on time when the app crashes at startup.
What's also weird is that those affected users cannot fix the issue by reinstalling the app. So it seems to be very specifically reproducible for those users.
We could try to fork the SDK & comment out the assert, just to try to have a workaround. That could of course still cause weird issues if the PFUser
or PFInstallation
isn't of it's own class.
It has been fixed by us simply recompiling the same Parse version with Carthage on the latest Xcode 13.1 production command-line tools 🙌, where we previously compiled it with Xcode 13.0
So it looks like it was a weird compiler bug after all 😅
New Issue Checklist
Issue Description
Our users with iOS 13 report a crash @ app start, that we cannot reproduce in the simulator. The stack trace is clear however:
Crash log
``` Last Exception Backtrace: 0 CoreFoundation 0x1bf342a48 0x1bf217000 + 1227336 1 libobjc.A.dylib 0x1bf069fa4 0x1bf064000 + 24484 2 CoreFoundation 0x1bf2381c0 0x1bf217000 + 135616 3 FMCore 0x104901190 +[PFObject(Private) _assertValidInstanceClassName:] + 6459792 (PFObject.m:773) 4 FMCore 0x104906c18 -[PFObject init] + 6482968 (PFObject.m:1673) 5 FMCore 0x104906e94 -[PFObject initWithObjectState:] + 6483604 (PFObject.m:1698) 6 FMCore 0x104906f8c +[PFObject objectWithClassName:objectId:completeData:] + 6483852 (PFObject.m:1706) 7 FMCore 0x104907394 +[PFObject object] + 6484884 (PFObject.m:1748) 8 FMCore 0x104910870 __56-[PFCurrentInstallationController getCurrentObjectAsync]_block_invoke.37 + 6522992 (PFCurrentInstallationController.m:121) 9 Bolts 0x10508b41c __62-[BFTask continueWithExecutor:successBlock:cancellationToken:]_block_invoke + 46108 (BFTask.m:398) 10 Bolts 0x10508ae68 __55-[BFTask continueWithExecutor:block:cancellationToken:]_block_invoke + 44648 (BFTask.m:331) 11 Bolts 0x105090890 __29+[BFExecutor defaultExecutor]_block_invoke_2 + 67728 (BFExecutor.m:65) 12 Bolts 0x105090da4 -[BFExecutor execute:] + 69028 (BFExecutor.m:131) 13 Bolts 0x10508aac8 -[BFTask runContinuations] + 43720 (BFTask.m:307) 14 Bolts 0x10508a62c -[BFTask trySetResult:] + 42540 (BFTask.m:247) 15 Bolts 0x105087d3c -[BFTaskCompletionSource trySetResult:] + 32060 (BFTaskCompletionSource.m:66) 16 FMCore 0x1048e3e68 __28-[PFAsyncTaskQueue enqueue:]_block_invoke_2 + 6340200 (PFAsyncTaskQueue.m:0) 17 Bolts 0x10508ae68 __55-[BFTask continueWithExecutor:block:cancellationToken:]_block_invoke + 44648 (BFTask.m:331) 18 libdispatch.dylib 0x1bf00e610 0x1befb3000 + 374288 19 libdispatch.dylib 0x1bf00f184 0x1befb3000 + 377220 20 libdispatch.dylib 0x1befb76f8 0x1befb3000 + 18168 21 libdispatch.dylib 0x1befc3fa4 0x1befb3000 + 69540 22 libdispatch.dylib 0x1befc4770 0x1befb3000 + 71536 23 libsystem_pthread.dylib 0x1bf05eb48 0x1bf053000 + 47944 24 libsystem_pthread.dylib 0x1bf061760 0x1bf053000 + 59232 ```It seems related to this issue: https://github.com/parse-community/Parse-SDK-iOS-OSX/issues/1297 however, we don't use a
PFUser
subclass with an underscore in our code. Could it be that iOS 15 bridges code to Swift differently? That it adds an underscore somehow, specifically on iOS 13? We are at a loss for what to do about this.Please tell me what I can do to narrow this down.
Steps to reproduce
It seems to happen at initialization of the Parse SDK (
Parse.initialize(with: parseConfig)
) or when querying the.current()
ofPFUser
. We cannot see exactly where it happens in our own code, which isn't that helpful.Actual Outcome
Crash at startup for some iOS 13 users
Expected Outcome
No crash at intialization
Environment
All iOS 13 versions. We have a minimum of iOS 11, where we don't see this issue on 11 and 12 versions. The amount is 169 users in the last 30 days with a total of 1713 crashes. We are only seeing this crash occurring from our app version where we first brought iOS 15 support (so a binary built with iOS 15). Haven't changed any user-management code in that release.
Client
Logs
Cannot access app logs, as the users crashes @ startup
Crash log
``` Last Exception Backtrace: 0 CoreFoundation 0x1bf342a48 0x1bf217000 + 1227336 1 libobjc.A.dylib 0x1bf069fa4 0x1bf064000 + 24484 2 CoreFoundation 0x1bf2381c0 0x1bf217000 + 135616 3 FMCore 0x104901190 +[PFObject(Private) _assertValidInstanceClassName:] + 6459792 (PFObject.m:773) 4 FMCore 0x104906c18 -[PFObject init] + 6482968 (PFObject.m:1673) 5 FMCore 0x104906e94 -[PFObject initWithObjectState:] + 6483604 (PFObject.m:1698) 6 FMCore 0x104906f8c +[PFObject objectWithClassName:objectId:completeData:] + 6483852 (PFObject.m:1706) 7 FMCore 0x104907394 +[PFObject object] + 6484884 (PFObject.m:1748) 8 FMCore 0x104910870 __56-[PFCurrentInstallationController getCurrentObjectAsync]_block_invoke.37 + 6522992 (PFCurrentInstallationController.m:121) 9 Bolts 0x10508b41c __62-[BFTask continueWithExecutor:successBlock:cancellationToken:]_block_invoke + 46108 (BFTask.m:398) 10 Bolts 0x10508ae68 __55-[BFTask continueWithExecutor:block:cancellationToken:]_block_invoke + 44648 (BFTask.m:331) 11 Bolts 0x105090890 __29+[BFExecutor defaultExecutor]_block_invoke_2 + 67728 (BFExecutor.m:65) 12 Bolts 0x105090da4 -[BFExecutor execute:] + 69028 (BFExecutor.m:131) 13 Bolts 0x10508aac8 -[BFTask runContinuations] + 43720 (BFTask.m:307) 14 Bolts 0x10508a62c -[BFTask trySetResult:] + 42540 (BFTask.m:247) 15 Bolts 0x105087d3c -[BFTaskCompletionSource trySetResult:] + 32060 (BFTaskCompletionSource.m:66) 16 FMCore 0x1048e3e68 __28-[PFAsyncTaskQueue enqueue:]_block_invoke_2 + 6340200 (PFAsyncTaskQueue.m:0) 17 Bolts 0x10508ae68 __55-[BFTask continueWithExecutor:block:cancellationToken:]_block_invoke + 44648 (BFTask.m:331) 18 libdispatch.dylib 0x1bf00e610 0x1befb3000 + 374288 19 libdispatch.dylib 0x1bf00f184 0x1befb3000 + 377220 20 libdispatch.dylib 0x1befb76f8 0x1befb3000 + 18168 21 libdispatch.dylib 0x1befc3fa4 0x1befb3000 + 69540 22 libdispatch.dylib 0x1befc4770 0x1befb3000 + 71536 23 libsystem_pthread.dylib 0x1bf05eb48 0x1bf053000 + 47944 24 libsystem_pthread.dylib 0x1bf061760 0x1bf053000 + 59232 ```Crash logs in Firebase Crashlytics
![image](https://user-images.githubusercontent.com/7554912/142403534-56ff452b-6cca-4d37-a4ba-51a59d59c17d.png)