Runtime icon indicating copy to clipboard operation
Runtime copied to clipboard

Factory tests fail on Linux

Open robertjpayne opened this issue 6 years ago • 3 comments

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?

robertjpayne avatar Aug 03 '19 15:08 robertjpayne

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?

wickwirew avatar Aug 04 '19 22:08 wickwirew

Is there any progress on this issue?

bauer-andreas avatar Jun 30 '21 22:06 bauer-andreas

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 requiredAlignmentMask parameter "always one less than a power of 2 that's at least alignof(void*)"
  • The isAlignmentMask assertion (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.

bauer-andreas avatar Jul 01 '21 13:07 bauer-andreas