App crash when launch from TestFlight/Optimized Release Build (+[RXObjCRuntime(swizzle) load])
MussaCharles opened this issue · comments
Short description of the issue:
App crash when launch from TestFlight but runs okay when run direct from Xcode to device.
Specifically when archived with scheme build configuration set to Release
and distribute app via TestFlight the app crashes on launch but works fine if deployed with scheme build configuration set to Debug
.
Expected outcome:
App launch without crash when ran from TestFlight.
What actually happens:
App Crashes immediately on launch.
Self contained code example that reproduces the issue:
Crash log
Incident Identifier: 259BB6B3-05A3-4355-91F3-A69D7BCADB13
Beta Identifier: CAD6C329-XXXXX-4DDA-BBCF-XXXXXXXXXXXX
Hardware Model: iPhone12,5
Process: MyAppName [84243]
Path: /private/var/containers/Bundle/Application/1ddsS-910F-1XXX-5XX-71161C9FC906/MyAppName.app/MyAppName
Identifier: MyAppBundleIdentifer
Version: 9.2.0 (1)
AppStoreTools: 14B44
AppVariant: 1:iPhone12,5:15
Beta: YES
Code Type: ARM-64 (Native)
Role: Foreground
Parent Process: launchd [1]
Coalition: MyAppBundleIdentifer [18819]
Date/Time: 2022-11-10 13:55:48.4530 +0900
Launch Time: 2022-11-10 13:55:48.2830 +0900
OS Version: iPhone OS 15.4.1 (19E258)
Release Type: User
Baseband Version: 3.02.01
Report Version: 104
Exception Type: EXC_BAD_ACCESS (SIGBUS)
Exception Subtype: UNKNOWN_0x101 at 0x8010000000000931 -> 0x0000000000000931 (possible pointer authentication failure)
Exception Codes: 0x0000000000000101, 0x8010000000000931
VM Region Info: 0x931 is not in any region. Bytes before following region: 4309300943
REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL
UNUSED SPACE AT START
--->
__TEXT 100dac000-100ec0000 [ 1104K] r-x/r-x SM=COW ...3.app/MyAppName
Exception Note: EXC_CORPSE_NOTIFY
Termination Reason: SIGNAL 10 Bus error: 10
Terminating Process: exc handler [84243]
Triggered by Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 ??? 0x931 ???
1 libobjc.A.dylib 0x19d973e8c CALLING_SOME_+initialize_METHOD + 24
2 libobjc.A.dylib 0x19d969490 initializeNonMetaClass + 608
3 libobjc.A.dylib 0x19d96db9c initializeAndMaybeRelock(objc_class*, objc_object*, mutex_tt<false>&, bool) + 184
4 libobjc.A.dylib 0x19d966c68 lookUpImpOrForward + 912
5 libobjc.A.dylib 0x19d962384 _objc_msgSend_uncached + 68
6 MyAppName 0x101430030 +[RXObjCRuntime(swizzle) load] + 6832176 (_RXObjCRuntime.m:559)
7 libobjc.A.dylib 0x19d96fa74 load_images + 824
8 dyld 0x103335f5c dyld4::RuntimeState::notifyObjCInit(dyld4::Loader const*) + 164
9 dyld 0x10333a578 dyld4::Loader::runInitializersBottomUp(dyld4::RuntimeState&, dyld3::Array<dyld4::Loader const*>&) const + 204
10 dyld 0x1033407ac dyld4::Loader::runInitializersBottomUpPlusUpwardLinks(dyld4::RuntimeState&) const + 124
11 dyld 0x1033604a0 dyld4::APIs::runAllInitializersForMain() + 312
12 dyld 0x10334b76c dyld4::prepare(dyld4::APIs&, dyld3::MachOAnalyzer const*) + 3060
13 dyld 0x103349cc4 start + 488
Thread 0 crashed with ARM Thread State (64-bit):
x0: 0x0000000102b0e8d8 x1: 0x00000001cf818ab2 x2: 0x000000028269d9c0 x3: 0x000000028269d9e0
x4: 0x0000000000000000 x5: 0x0000000000000001 x6: 0x0000000000000011 x7: 0x0000000000000920
x8: 0x0000000102abc000 x9: 0x0000000000000103 x10: 0x0000000280898800 x11: 0x000000019d98ec51
x12: 0x0000000000000007 x13: 0x0000000000000006 x14: 0x0000000000000000 x15: 0xffffffffffffffff
x16: 0x8010000000000931 x17: 0x000000019d97282c x18: 0x0000000000000000 x19: 0x0000000102b0e8d8
x20: 0x00000001ceae7f3a x21: 0x0000000102acb000 x22: 0x0000000102bcf000 x23: 0x00000001ddd2e000
x24: 0x000000000000000b x25: 0x00000001ddd2f378 x26: 0x000000010339c660 x27: 0x00000001ddd2e000
x28: 0x00000001dbd38000 fp: 0x000000016f04e3d0 lr: 0x0000000101430524
sp: 0x000000016f04e3b0 pc: 0x8010000000000931 cpsr: 0x40000000
far: 0x8010000000000931 esr: 0x8a000000 (PC alignment)
Binary Images:
0x0 - 0xffffffffffffffff ??? unknown-arch <00000000000000000000000000000000> ???
0x19d960000 - 0x19d99cfff libobjc.A.dylib arm64e <a196a0f6cadb325bbc1f5965e670f9b6> /usr/lib/libobjc.A.dylib
0x100dac000 - 0x10283bfff MyAppName arm64 <adafsdklj2fe9dbddb3k8f2c84f7232adk2> /private/var/containers/Bundle/Application/5F48C2DC-9124-478E-87A1-7110099/MyAppName.app/MyAppName
0x1adadl00 - 0x103akdlj7fff dyld arm64e <d16b7kljd6193e4892622c1skdljsakd> /usr/lib/dyld
Error Formulating Crash Report:
PC register does not match crashing frame (0x8010000000000931 vs 0x931)
EOF
Similar crash can be reproduced using Ad hoc distribution option.
RxSwift/RxCocoa/RxBlocking/RxTest version/commit
RxCocoa/6.5.0/b4307ba
Platform/Environment
- iOS
- macOS
- tvOS
- watchOS
- playgrounds
How easy is to reproduce? (chances of successful reproduce after running the self contained code)
- easy, 100% repro
- sometimes, 10%-100%
- hard, 2% - 10%
- extremely hard, %0 - 2%
Xcode version:
13.3.1
Installation method:
- Swift Package Manager (SPM)
- CocoaPods
- Carthage
- Git submodules
I have multiple versions of Xcode installed:
(so we can know if this is a potential cause of your issue)
- yes (which ones)
- no
Level of RxSwift knowledge:
(this is so we can understand your level of knowledge
and formulate the response in an appropriate manner)
- just starting
- I have a small code base
- I have a significant code base
Still investigating, Seems to be related to this Apple documentation Preparing your app to work with pointer authentication
Any thoughts on this issue?
@freak4pc @kzaher @thedavidharris @cltnschlosser
Affected file -> https://github.com/ReactiveX/RxSwift/blob/main/RxCocoa/Runtime/_RXObjCRuntime.m
I successfully resolved the issue.
I am leaving detailed description below to help others who might face the same issue in the future.
After diving deep in my project, I finally found the reason to why this crash was triggered.
It turns out that Inject was causing the crash however crash logs was pointing to +(void)load {..} declared in _RXObjCRuntime.m which I think it's because it Swizzle method calls 🤔.
A summary about my project.
A mixture of Swift & Objective-C which is modularized using local Swift Packages (SPM) among those,
10 packages use RxSwift as a dependency.
Also the main app target uses RxSwift as a dependency.
My current guess is what Apple mentioned here about pointer authentication which I think Inject was triggering and strangely propagate all the way to _RXObjCRuntime.
To summarize based on Inject documentation, I was supposed to set -Xlinker -interposable
as well as addressing other limitations mentioned here. I did as instructed on the main app target via Xcode. However, since I am using lots of local SwiftPM, I forgot to do the same on all SPMs which were using Inject as a dependecy as mentioned on SE-0238.
I was able to successfully resolve the issue.
Even though this issue might not be directly caused by RxSwift/RxCocoa since crash logs points to +(void)load {..} Maybe documentation on how to disable RxCocoa Swizzling or avoid triggering relevant class etc.. should be added so as to speed up debugging in such hidden bugs.