Async Await crash on iOS14 with Xcode 13.2.1

Assuming that you're targeting iOS 13+ shouldn't the binary link libswift_Concurrency not weakly? I noticed some of the other swift libraries are also weak like this that I assume could also not be since they are also required?

Interesting, I had assumed it would as well, but with just that change (like this Comparing main...bitcode-mode · keith/backdeploy-concurrency-crash · GitHub) I see this crash on my iOS 13 device:

* thread #1, stop reason = EXC_BAD_ACCESS (code=1, address=0x1831de43c)
  * frame #0: 0x000000010235dd78 dyld`dyld3::MachOAnalyzer::forEachObjCMethod(unsigned long long, bool, void (unsigned long long, dyld3::MachOAnalyzer::ObjCMethod const&) block_pointer) const + 224
    frame #1: 0x000000010235d128 dyld`invocation function for block in dyld3::MachOAnalyzer::forEachObjCClass(Diagnostics&, bool, void (Diagnostics&, unsigned long long, unsigned long long, unsigned long long, dyld3::MachOAnalyzer::ObjCClassInfo const&, bool) block_pointer) const + 504
    frame #2: 0x0000000102353a2c dyld`invocation function for block in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const + 544
    frame #3: 0x0000000102352c4c dyld`dyld3::MachOFile::forEachLoadCommand(Diagnostics&, void (load_command const*, bool&) block_pointer) const + 168
    frame #4: 0x00000001023537c4 dyld`dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const + 180
    frame #5: 0x000000010235cf14 dyld`dyld3::MachOAnalyzer::forEachObjCClass(Diagnostics&, bool, void (Diagnostics&, unsigned long long, unsigned long long, unsigned long long, dyld3::MachOAnalyzer::ObjCClassInfo const&, bool) block_pointer) const + 204
    frame #6: 0x000000010236a5a8 dyld`dyld3::closure::ClosureBuilder::optimizeObjCSelectors(objc_opt::objc_selopt_t const*, dyld3::Map<char const*, dyld3::closure::Image::ObjCImageOffset, dyld3::closure::ClosureBuilder::HashCString, dyld3::closure::ClosureBuilder::EqualCString> const&, dyld3::closure::ClosureBuilder::ObjCOptimizerImage&) + 588
    frame #7: 0x00000001023691e0 dyld`dyld3::closure::ClosureBuilder::optimizeObjC(dyld3::Array<dyld3::closure::ImageWriter>&) + 876
    frame #8: 0x000000010236d364 dyld`dyld3::closure::ClosureBuilder::makeLaunchClosure(dyld3::closure::LoadedFileInfo const&, bool) + 1176
    frame #9: 0x0000000102333f1c dyld`dyld::buildLaunchClosure(unsigned char const*, dyld3::closure::LoadedFileInfo const&, char const**) + 368
    frame #10: 0x0000000102332b0c dyld`dyld::_main(macho_header const*, unsigned long, int, char const**, char const**, char const**, unsigned long*) + 2844
    frame #11: 0x000000010232d22c dyld`dyldbootstrap::start(dyld3::MachOLoaded const*, int, char const**, dyld3::MachOLoaded const*, unsigned long*) + 432
    frame #12: 0x000000010232d038 dyld`_dyld_start + 56

The details from the device are similarly slim:

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x000000018391243c
Termination Signal: Segmentation fault: 11
Termination Reason: Namespace SIGNAL, Code 0xb
Terminating Process: exc handler [650]
Highlighted by Thread:  0

Backtrace not available

Unknown thread crashed with ARM Thread State (64-bit):
    x0: 0x000000016d609d50   x1: 0x0000000000000008   x2: 0x0000000000000000   x3: 0x0000000000000000
    x4: 0x000000016d609d20   x5: 0x0000000000000000   x6: 0x7366657272657075   x7: 0x0000000000000d60
    x8: 0x000000008000000c   x9: 0x000000016d609e93  x10: 0x0000000000046430  x11: 0x0000000000000004
   x12: 0x0000000000ff0006  x13: 0x0000000000048000  x14: 0x0000000000000000  x15: 0x0000000102b8c018
   x16: 0xfffffffffffffff6  x17: 0x0000000102a858d4  x18: 0x0000000000000000  x19: 0x000000016d609e3b
   x20: 0x0000000000000000  x21: 0x00000001038cc000  x22: 0x0000000000000000  x23: 0x0000000000000001
   x24: 0x000000008004643c  x25: 0x0000000000000001  x26: 0x000000016d609e93  x27: 0x0000000103912428
   x28: 0x000000018391243c   fp: 0x000000016d609ef0   lr: 0x0605290102a91e24
    sp: 0x000000016d609db0   pc: 0x0000000102a91d78 cpsr: 0x80000000
   esr: 0x00000000  Address size fault

Binary images description not available

Error Formulating Crash Report:
Failed to create CSSymbolicatorRef - corpse still valid ¯\_(ツ)_/¯

EOF

@Douglas_Gregor Makes sense! We will try the scripts in the meantime and will report back if we find any issues. Thanks!

It was intentional. There are is an unfortunate configuration where folks build binaries that use concurrency on iOS 15/macOS 12+ but deploy earlier and aren't app bundles (e.g., a command-line utility that's not within an app bundle). Non-weak linkage breaks these programs on launch; weak linkage allows them to continue to work so long as they are careful not to actually use concurrency on older OS versions. Aside from a small launch-time cost on older OS versions, using weak linking here doesn't hurt.

I'm not seeing this crash on iOS 14, perhaps because iOS 13 isn't expecting to see bitcode at all. It implies that BITCODE_GENERATION_MODE=bitcode isn't a viable workaround for everyone. The script that lipo's out the arm64e slice seems to be the best workaround for now.

Doug

2 Likes

I wonder for this case if it would also be better to strongly link the framework, given that folks who don't understand the inner workings of copying dylibs might not know about this, and hope to target older OS versions and have this "just work", IMO it might actually be nice to be explicit about having them weak link the target, but I also understand that less configuration can be nicer in some cases.

Either way my only thought is maybe this issue would have been caught sooner if it wasn't weakly linked, but I'm glad we found a resolution, thanks everyone!

This crash seems to occur only with debug build runs from Home Screen. To test this theory, I tested the code without build script provided by Sergey, in Adhoc and Test Flight build and it did not crash.

Could you guys explain why it is crashing only for debug build run from Home Screen? What is the difference between debug build from Xcode and run from Home Screen? Thanks!

This appears to be the same issue I ran into last month here — Using actor in iOS 14 crashes on initialization using Xcode 13.2

I can confirm that my app works when run initially from Xcode, but terminating the app and relaunching from the Home Screen crashes with the same 0x0000000000000000 EXC_BAD_ACCESS error.

It seems like the issue is reproducible / others are experiencing the problem now but I'm happy to help with any debugging as well.

When running from Xcode, some DYLD environment variables are automatically set, which force the process to load the arm64 slice rather than failing to load the shared library. As Keith showed, unchecking all of the options in the scheme that map to DYLD environment variables (eg, Main Thread Checker) will result in the program crashing on launch from Xcode as well.

Doug

Makes sense and thank you very much @Douglas_Gregor . I know you already answered this question but going to ask again :) Any thoughts when a new Xcode version resolving this issue would be released? Just a ball park, One week, one month?

Jay Muthialu

(post deleted by author)

Release builds (build with Xcode in release mode and then launch the app from the home screen) are also affected exactly the same way.

Is this a blocker for you? I downgraded to Xcode 13.1 because of this issue, but maybe I'm alright with that only because I don't need something new/fancy that's only available in Xcode 13.2.

Correct. Anything via Xcode.

Is this a blocker for you?

Not a hard blocker. We are upgrading to new concurrency APIs which we love very much (thanks Apple team). I have tested with the script provided by @zavsby and it works great. But we are bit cautious and we would prefer to go with a resolution through Xcode version bump. If that takes lot of time then we would go with the script.

Many many thanks for all the contributors here to help debug the issue very quickly and provide a workaround. Thank you all so so much!!

Jay Muthialu

Using SwiftUI in XCode 13.2.1 triggers the inclusion of the Concurrency compatibility libraries in your app even if you use no concurrency anywhere in your own code.

1 Like

This is odd. We are using Bitcode and have SwiftUI in part of the app and Xcode 13.2.1 on the CI agents and the apps have been tested on iOS 14 without crashes… :/…

1 Like

Note that the crash is experienced on device only

1 Like

We are checking on real devices using TestFlight builds in iOS14 and iOS 15 devices (iOS 13 being set as min deployment SDK). Will run another test as we have bitcode and non bitcode enabled apps too and I wonder if that could affect things.

@Panajev Try this step and it most probably will crash if you are using Xcode 13.2.1.

  • Run your app (debug build) from Xcode to your device.
  • Stop the application.
  • Launch the app from Home Screen (don't run from Xcode second time).
  • It should crash now.

In my testing this is the workflow that crashes. Any archived build such as Adhoc and Test Flight are working fine.

Jay Muthialu

2 Likes

This is odd, as rearranging the SwiftUI code (essentially the workaround posted in the dev forums link from my original post) led the crash not to happen. We tested archived release builds, non-archived release builds, and non-archived debug builds. It is currently on the App Store with no reported crashes. So it’s not just using SwiftUI which causes the crash I posted. Therefore I now think this thread is actually about a slightly different issue than the one I linked.

1 Like

Hello,

A new Xcode beta is out, but the release notes do not say anything about fixing this crash.
@Douglas_Gregor is a fix for this bug included in this release? If not, then will it be included in the next beta of Xcode 13.3?

Thanks

Looks like it's included:

before:

% file /Applications/Xcode-13.2.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/iphoneos/libswift_Concurrency.dylib
/Applications/Xcode-13.2.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/iphoneos/libswift_Concurrency.dylib: Mach-O universal binary with 2 architectures: [arm64:Mach-O 64-bit dynamically linked shared library arm64] [arm64e]
/Applications/Xcode-13.2.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/iphoneos/libswift_Concurrency.dylib (for architecture arm64):   Mach-O 64-bit dynamically linked shared library arm64
/Applications/Xcode-13.2.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/iphoneos/libswift_Concurrency.dylib (for architecture arm64e):  Mach-O 64-bit dynamically linked shared library arm64e

after:

% file /Applications/Xcode-13.3.0-beta1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/iphoneos/libswift_Concurrency.dylib
/Applications/Xcode-13.3.0-beta1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/iphoneos/libswift_Concurrency.dylib: Mach-O 64-bit dynamically linked shared library arm64

Yes, this issue is fixed in Xcode 13.3 beta 1. The back-deployment shared libraries (lib/swift-5.5/<platform>/libswift_Concurrency.dylib) are also compatible with Xcode 13.2 because there were no compiler changes that affected back-deployment here.

Doug

4 Likes