Swift Package crashes while copy&paste code works

Hello, I was researching an interesting problem related to Swift Packages but I'm not able to find the solution so, here we go!


Here is the scenario:


- Create an empty project in Xcode for iOS app.

- Import Swift Package: https://bitbucket.org/janmazurczak/seed

- In AppDelegate import Seed

- In AppDelegate.didFinishLaunching paste this:

let someSeed = TimeSeed<UInt32>(sliceDuration: 15, modifier: "seedModifier", date: Date())

- Run and observe a crash


And then:


- Remove Swift Package dependency

- Go to package repo, download swift files and paste them in the project, like it is regular part of the project, without packages importing.

- In AppDelegate remove import Seed

- Run and observe NO crash.


Expected:

The same code should work via packages the same way.


Note about modularity:

Because Swift Package is a separate module it should respect public/internal/private differently than files dropped into the project directly so to check this I've created a Framework locally and added it to the workspace to mimic separate module. The results I've observed were that everything compiled and run fine, so problem is definetely related to Swift Packages.


Note about other packages:

I tried to import another packages created by me an I experienced the same problem so maybe package manifest file is where I made a mistake.


Any thoughts?

Accepted Reply

I can confirm that without further changes in my packages problem disappeared at least with Xcode version 11.4.1 (11E503a).

It was indeed some compiling issue which should be solved now.

Thank you for support and for spotting the dangling pointers 🙂

Replies

Run and observe a crash

What does this crash look like?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

EXC_BAD_ACCESS Crash happens in my library but it never occurs when you use the same swift files without importing a package.

There are many potential causes for

EXC_BAD_ACCESS
. It’s hard to offer any concrete advice without more details. Can you post a symbolicated Apple crash report?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Here it is but I think you're missing the point that the same swift code works perfectly well when it's not in swift package.

In first post I delivered everything needed to reproduce this behaviour including original swift package repository.


Is it possible that I've been using this code successfully in number of apps but moving it to Swift Package exposed a problem? Or moving to Swift Package rather caused the problem?


AddressSanitizer:DEADLYSIGNAL
=================================================================
==60207==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000064 (pc 0x00010eb30ee1 bp 0x7ffee10e9b30 sp 0x7ffee10e9970 T0)
==60207==The signal is caused by a READ memory access.
==60207==Hint: address points to the zero page.
atos(60208,0x10f402dc0) malloc: enabling scribbling to detect mods to free blocks
2019-11-14 00:07:32.873297+0100 atos[60208:2174668] examining /[path]/TEST TO REMOVE.app/TEST TO REMOVE [60207]
    #0 0x10eb30ee0 in $sSayxGSzRzlWOh (TEST TO REMOVE:x86_64+0x10001dee0)
    #1 0x10eb39ab1 in $s4Seed11SeedsBridgeC4syncyyF (TEST TO REMOVE:x86_64+0x100026ab1)
    #2 0x10eb39874 in $s4Seed11SeedsBridgeC5seedA0D1BACyxGA2ACyxG_AHtcfc (TEST TO REMOVE:x86_64+0x100026874)
    #3 0x10eb3938f in $s4Seed11SeedsBridgeC5seedA0D1BACyxGA2ACyxG_AHtcfC (TEST TO REMOVE:x86_64+0x10002638f)
    #4 0x10eb239ed in $s4Seed27MultidimensionalSeedsBridgeC10dimensions12seedModifier8positionACyxGSayAA13DimensionInfoVG_SSSaySdGtcfc (TEST TO REMOVE:x86_64+0x1000109ed)
    #5 0x10eb3f6dc in $s4Seed04TimeA0C13sliceDuration8modifier4dateACyxGSi_SS10Foundation4DateVtcfc (TEST TO REMOVE:x86_64+0x10002c6dc)
    #6 0x10eb3f008 in $s4Seed04TimeA0C13sliceDuration8modifier4dateACyxGSi_SS10Foundation4DateVtcfC (TEST TO REMOVE:x86_64+0x10002c008)
    #7 0x10eb15322 in $s14TEST_TO_REMOVE11AppDelegateC11application_29didFinishLaunchingWithOptionsSbSo13UIApplicationC_SDySo0l6LaunchK3KeyaypGSgtF AppDelegate.swift:31
    #8 0x10eb155f6 in $s14TEST_TO_REMOVE11AppDelegateC11application_29didFinishLaunchingWithOptionsSbSo13UIApplicationC_SDySo0l6LaunchK3KeyaypGSgtFTo 
    #9 0x11d733787 in -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] (UIKitCore:x86_64+0xaac787)
    #10 0x11d735196 in -[UIApplication _callInitializationDelegatesWithActions:forCanvas:payload:fromOriginatingProcess:] (UIKitCore:x86_64+0xaae196)
    #11 0x11d73ace5 in -[UIApplication _runWithMainScene:transitionContext:completion:] (UIKitCore:x86_64+0xab3ce5)
    #12 0x11ce71401 in -[_UISceneLifecycleMultiplexer completeApplicationLaunchWithFBSScene:transitionContext:] (UIKitCore:x86_64+0x1ea401)
    #13 0x11d737285 in -[UIApplication _compellApplicationLaunchToCompleteUnconditionally] (UIKitCore:x86_64+0xab0285)
    #14 0x11d737584 in -[UIApplication _run] (UIKitCore:x86_64+0xab0584)
    #15 0x11d73cb47 in UIApplicationMain (UIKitCore:x86_64+0xab5b47)
    #16 0x10eb168aa in main AppDelegate.swift:16
    #17 0x1145a5c24 in start (libdyld.dylib:x86_64+0xc24)
==60207==Register values:
rax = 0x0000000112bc3d80  rbx = 0x00007ffee10e9a20  rcx = 0x0000000112bc3d80  rdx = 0x00001000225787b0  
rdi = 0x0000000000000064  rsi = 0x0000100000000000  rbp = 0x00007ffee10e9b30  rsp = 0x00007ffee10e9970  
 r8 = 0x0000000000000020   r9 = 0x00001fffdc21d330  r10 = 0x0000000000000008  r11 = 0x0000000112acaf90  
r12 = 0x0000000000000001  r13 = 0x0000606000066e00  r14 = 0x0000000000000008  r15 = 0x0000000000000008  
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (TEST TO REMOVE:x86_64+0x10001dee0) in $sSayxGSzRzlWOh

Here it is

Thanks.

but I think you're missing the point that the same swift code works perfectly well when it's not in swift package.

It’s not that I don’t believe you, it’s that there are many different reasons why code can fail when you move it between components. For example, recently there’s been a spate of problems caused by a bug in the way that Swift handles runtime information in this case. OTOH, there’s a world of undefined behaviour that can easily trigger issues like this.

In first post I delivered everything needed to reproduce this behaviour including original swift package repository.

Right, but a quick glance at a crash report is a lot quicker than setting up a test project.

Anyway, on to your crash. Here’s those symbols demangled:

$ cat tmp.txt
$sSayxGSzRzlWOh
$s4Seed11SeedsBridgeC4syncyyF
$s4Seed11SeedsBridgeC5seedA0D1BACyxGA2ACyxG_AHtcfc
$s4Seed11SeedsBridgeC5seedA0D1BACyxGA2ACyxG_AHtcfC
$s4Seed27MultidimensionalSeedsBridgeC10dimensions12seedModifier8positionACyxGSayAA13DimensionInfoVG_SSSaySdGtcfc
$s4Seed04TimeA0C13sliceDuration8modifier4dateACyxGSi_SS10Foundation4DateVtcfc
$s4Seed04TimeA0C13sliceDuration8modifier4dateACyxGSi_SS10Foundation4DateVtcfC
$s14TEST_TO_REMOVE11AppDelegateC11application_29didFinishLaunchingWithOptionsSbSo13UIApplicationC_SDySo0l6LaunchK3KeyaypGSgtF
$s14TEST_TO_REMOVE11AppDelegateC11application_29didFinishLaunchingWithOptionsSbSo13UIApplicationC_SDySo0l6LaunchK3KeyaypGSgtFTo
$ xcrun swift-demangle < tmp.txt
outlined destroy of [A]
Seed.SeedsBridge.sync() -> ()
Seed.SeedsBridge.init(seedA: Seed.Seed<A>, seedB: Seed.Seed<A>) -> Seed.SeedsBridge<A>
Seed.SeedsBridge.__allocating_init(seedA: Seed.Seed<A>, seedB: Seed.Seed<A>) -> Seed.SeedsBridge<A>
Seed.MultidimensionalSeedsBridge.init(dimensions: [Seed.DimensionInfo], seedModifier: Swift.String, position: [Swift.Double]) -> Seed.MultidimensionalSeedsBridge<A>
Seed.TimeSeed.init(sliceDuration: Swift.Int, modifier: Swift.String, date: Foundation.Date) -> Seed.TimeSeed<A>
Seed.TimeSeed.__allocating_init(sliceDuration: Swift.Int, modifier: Swift.String, date: Foundation.Date) -> Seed.TimeSeed<A>
TEST_TO_REMOVE.AppDelegate.application(_: __C.UIApplication, didFinishLaunchingWithOptions: [__C.UIApplicationLaunchOptionsKey : Any]?) -> Swift.Bool
@objc TEST_TO_REMOVE.AppDelegate.application(_: __C.UIApplication, didFinishLaunchingWithOptions: [__C.UIApplicationLaunchOptionsKey : Any]?) -> Swift.Bool

Here’s what the last frame for your code looks like:

public func sync() {
    let utilised = utilisedNumbersCount
    restore(utilisedNumbersCount: utilised)
}

It seems that the crash is actually on line 2 of that, where you get the

utilisedNumbersCount
property. That property is backed by a getter, and it’s definitely crashing before it comes back from that getter, even though the getter doesn’t appear in the backtrace.

Here’s the code for that getter:

open var utilisedNumbersCount: Int {
    return max(seedA.utilisedNumbersCount, seedB.utilisedNumbersCount)
}

There’s only one line here, so it’s hard to see what’s going on. I broke this up into multiple lines:

open var utilisedNumbersCount: Int {
    let a = seedA.utilisedNumbersCount
    let b = seedB.utilisedNumbersCount
    let c = max(a, b)
    return c
}

It crashes as I step over line 2.

I don’t see anything obvious here, and digging into the assembler is more work than I have time for in the context of DevForums (I did learn a lot of about this by looking at the non-ASan crash, but the ASan crash gets us closer to the problem, which is nice, and radically obfuscates the assembly, which is not).

Anyway, as I mentioned above, there have been some Swift runtime issues with Xcode 11.2 so I thought I’d try installing the latest toolchain to see if that helps (specifically, I installed yesterday’s trunk snapshot from the Swift downloads page). That didn’t fix the problem, but it did highlight a bug in your code.

Specifically, it generated dangling pointer warnings on the following two methods:

public func data() -> Data {
    var mutableValue = self
    let buffer = UnsafeBufferPointer(start: &mutableValue, count: 1)
    return Data(buffer: buffer)
}

public func toInteger<T: BinaryInteger>() -> T {
    var value: T = 0
    let buffer = UnsafeMutableBufferPointer(start: &value, count: 1)
    _ = copyBytes(to: buffer)
    return value
}

My recommendation is that you fix these bugs and then re-test. If you continue to have problems, file a Swift bug and then ask about it over on Swift Forums.

Please post your bug number, just for the record.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

I've fixed dangling pointers:

extension BinaryInteger {
    public func data() -> Data {
        return withUnsafeBytes(of: self) { Data($0) }
    }
}

extension Data {
    public func toInteger<T: BinaryInteger>() -> T {
        return withUnsafeBytes { $0.load(as: T.self) }
    }
}


but no luck for the mentioned problem. I'll update as soon as I bump into anything new.

I've fixed dangling pointers:

Cool.

no luck for the mentioned problem.

No, I wasn’t expecting there to be, it’s just that there’s little point filing a bug with known issues like those.

Anyway, with that out of the way I do think your best course of action is to file a Swift bug and then ask about it over on Swift Forums.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

I can confirm that without further changes in my packages problem disappeared at least with Xcode version 11.4.1 (11E503a).

It was indeed some compiling issue which should be solved now.

Thank you for support and for spotting the dangling pointers 🙂