Hi folks! I've encountered a very strange segfault when instantiating a generic class with a protocol type constraint that only reproduces on Linux.
I first ran into this issue when trying to update Bazel's rules_swift to a newer grpc-swift version that depended on swift-atomics.
I created a demo project by forking swift-atomics, making a tiny binary that reproduced the issue, and then stripping out code until it had only the minimum necessary to reproduce the issue:
It's actually trivial to reproduce. You just need two targets, a swift library and a swift binary. The swift library contains three files:
AtomicValue.swift
public protocol AtomicValue {
}
AtomicBool.swift
extension Bool: AtomicValue {
}
ManagedAtomic.swift
public class ManagedAtomic<Value: AtomicValue> {
internal var _storage: Value
public init(_ value: Value) {
_storage = value
}
}
And the swift binary has just one file:
SwiftAtomicsTest.swift
import Atomics
@main
struct SwiftAtomicsTestMain {
static func main() throws {
print("before atomic")
let managedAtomic = ManagedAtomic(false)
print("after atomic")
}
}
The issue manifests on linux when the binary logs "before atomic" and then segfaults on the managedAtomic line:
ubuntu@focal:~/swift_atomics_test$ bazelisk run -s --compilation_mode=dbg --sandbox_debug //Sources/SwiftAtomicsTest
INFO: Analyzed target //Sources/SwiftAtomicsTest:SwiftAtomicsTest (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target //Sources/SwiftAtomicsTest:SwiftAtomicsTest up-to-date:
bazel-bin/Sources/SwiftAtomicsTest/SwiftAtomicsTest
INFO: Elapsed time: 0.113s, Critical Path: 0.00s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action
INFO: Running command line: bazel-bin/Sources/SwiftAtomicsTest/SwiftAtomicsTest
before atomic
ubuntu@focal:~/swift_atomics_test$
But you can see here that the same code builds and runs fine with swift build:
ubuntu@focal:~/swift_atomics_test$ swift build && ./.build/debug/SwiftAtomicsTest
Building for debugging...
Build complete! (0.04s)
before atomic
after atomic
ubuntu@focal:~/swift_atomics_test$
The code also works fine on macos with both build systems.
Also I found that merging the files into the binary (and not having a static library) or merging the AtomicBool and AtomicValue files resolved the issue.
Additionally, to remove any variables introduced by Bazel itself, I created a shell script that just invokes swiftc / clang with the same params and it can reproduce the issue as well:
Do you know what might be causing this issue or how I might be able to work around it? Thanks!