Runtime
Runtime copied to clipboard
Factory tests fail on Linux
I'm not 100% sure why but
testClass and testGenericClass are not part of the XCTestManifest and thus don't get run on Linux.
The first testClass fails on Linux with a segfault.
Are these methods supposed to work on Linux or not?
Not sure why either, ill have to take a look. Support was added last release to get those working on linux.
What swift version are you using btw?
Is there any progress on this issue?
Alright, so. I did some digging.
First of all, what I already uncovered yesterday was, that the createInstance call fails within the swift_allocObject call made to the Swift Runtime itself: https://github.com/wickwirew/Runtime/blob/5b82a3e74bd9fd5dfcad8e6ab8cc3f907aa4e235/Sources/Runtime/Factory/Factory.swift#L60-L67
Refer to the exemplary backtrace:
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x00007f5102e2ec02 in swift_allocObject () from /usr/lib/swift/linux/libswiftCore.so
#1 0x00005611ac5c3830 in $s7Runtime10buildClass4typeypypXp_tKF (type=...) at /usr/src/Runtime/Sources/Runtime/Factory/Factory.swift:67
#2 0x00005611ac5c3159 in $s7Runtime14createInstance2of11constructorypypXp_ypAA12PropertyInfoVKcSgtKF (type=..., constructor=...) at /usr/src/Runtime/Sources/Runtime/Factory/Factory.swift:46
#3 0x00005611ac5c2c9b in $s7Runtime14createInstance11constructorxypAA12PropertyInfoVKcSg_tKlF (constructor=...) at /usr/src/Runtime/Sources/Runtime/Factory/Factory.swift:28
#4 0x00005611ac5e5b50 in $s12RuntimeTests07FactoryB0C9testClassyyKF (self=...) at /usr/src/Runtime/Tests/RuntimeTests/FactoryTests.swift:59
#5 0x00005611ac612245 in $s12RuntimeTests07FactoryB0C05__allB0SaySS_yyKcACctGvpZfiyyKcACcfu3_yyKcfu4_ () at /usr/src/Runtime/Tests/RuntimeTests/XCTestManifests.swift:7
#6 0x00005611ac61acdf in $s12RuntimeTests07FactoryB0C05__allB0SaySS_yyKcACctGvpZfiyyKcACcfu3_yyKcfu4_TA ()
#7 0x00005611ac5e41af in $ss5Error_pIegzo_ytsAA_pIegrzo_TR ()
#8 0x00005611ac5e8c74 in $ss5Error_pIegzo_ytsAA_pIegrzo_TRTA ()
#9 0x00007f5101ffda5c in $syts5Error_pIegrzo_sAA_pIegzo_TRTA () from /usr/lib/swift/linux/libXCTest.so
#10 0x00007f5101ffd8b8 in $s6XCTest4test33_3BE257A46ADB477C7BF2D39968B39F9DLLyyAA0A4CaseCKcyyKcxcAERbzlFyAEKcfU_TA () from /usr/lib/swift/linux/libXCTest.so
#11 0x00007f5101ffd84f in $s6XCTest0A4CaseCs5Error_pIeggzo_ACytsAD_pIegnrzo_TRTA () from /usr/lib/swift/linux/libXCTest.so
#12 0x00007f5101ffdb16 in $s6XCTest0A4CaseCs5Error_pIeggzo_ACytsAD_pIegnrzo_TRTA.19 () from /usr/lib/swift/linux/libXCTest.so
#13 0x00007f5101fef528 in $s6XCTest0A4CaseCyts5Error_pIegnrzo_ACsAD_pIeggzo_TRTA () from /usr/lib/swift/linux/libXCTest.so
#14 0x00007f5101ffc1f8 in $s6XCTest0A4CaseC10invokeTestyyF () from /usr/lib/swift/linux/libXCTest.so
#15 0x00007f5101ffbfe3 in $s6XCTest0A4CaseC7performyyAA0A3RunCF () from /usr/lib/swift/linux/libXCTest.so
#16 0x00007f5101fff880 in $s6XCTestAAC3runyyF () from /usr/lib/swift/linux/libXCTest.so
#17 0x00007f5101ffddaf in $s6XCTest0A5SuiteC7performyyAA0A3RunCF () from /usr/lib/swift/linux/libXCTest.so
#18 0x00007f5101fff880 in $s6XCTestAAC3runyyF () from /usr/lib/swift/linux/libXCTest.so
#19 0x00007f5101ffddaf in $s6XCTest0A5SuiteC7performyyAA0A3RunCF () from /usr/lib/swift/linux/libXCTest.so
#20 0x00007f5101fff880 in $s6XCTestAAC3runyyF () from /usr/lib/swift/linux/libXCTest.so
#21 0x00007f5101ffac24 in $s6XCTest7XCTMain_9arguments9observerss5NeverOSayAA0A4CaseCm04testF5Class_SaySS_yAHKctG8allTeststG_SaySSGSayAA0A11Observation_pGtF () from /usr/lib/swift/linux/libXCTest.so
#22 0x00007f5101ffa5eb in $s6XCTest7XCTMainys5NeverOSayAA0A4CaseCm04testD5Class_SaySS_yAFKctG8allTeststGF () from /usr/lib/swift/linux/libXCTest.so
#23 0x00005611ac5e3d21 in main () at /usr/src/Runtime/Tests/LinuxMain.swift:8
Looking at the implementation two things caught my eye:
- The header file docs which state that the
requiredAlignmentMaskparameter "always one less than a power of 2 that's at least alignof(void*)" - The
isAlignmentMaskassertion (implemented here) which enforces that restriction.
As you can see in the code snippet above, we pass md.alignment to the Swift Runtime call, which follows the following calculations: https://github.com/wickwirew/Runtime/blob/5b82a3e74bd9fd5dfcad8e6ab8cc3f907aa4e235/Sources/Runtime/Metadata/MetadataType.swift#L60-L62
In the example of the FactoryTests.testClass() case the value passes is 8 which does not satisfy that requirement stated in the docs. Subtracting 1 agains resolves the issue and the test cases pass successfully. Not sure why it worked on macOS though (maybe some sort of compatibility layer).
In any case, instead of using md.alignment and according to the Class Metadata Layout docs we also can just use the ClassMetadataLayout.instanceAlignmentMask property: https://github.com/wickwirew/Runtime/blob/5b82a3e74bd9fd5dfcad8e6ab8cc3f907aa4e235/Sources/Runtime/Layouts/ClassMetadataLayout.swift#L43
To my tests it holds the expected value.