mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
58 lines
2.2 KiB
Swift
58 lines
2.2 KiB
Swift
// RUN: %empty-directory(%t)
|
|
// RUN: %target-build-swift -emit-library -o %t/dlopen_race.dylib %S/Inputs/dlopen_race_dylib.swift
|
|
// RUN: %target-build-swift -o %t/dlopen_race %s
|
|
// RUN: %target-codesign %t/dlopen_race %t/dlopen_race.dylib
|
|
// RUN: %target-run %t/dlopen_race %t/dlopen_race.dylib
|
|
// REQUIRES: executable_test
|
|
// REQUIRES: objc_interop
|
|
|
|
import StdlibUnittest
|
|
|
|
import Darwin
|
|
|
|
var DlopenRaceTests = TestSuite("DlopenRace")
|
|
|
|
typealias add_image_callback = @convention(c) (UnsafeRawPointer?, Int) -> Void
|
|
func register_func_for_add_image(_ f: add_image_callback) {
|
|
let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: -2)
|
|
let _dyld_register_func_for_add_image_ptr =
|
|
dlsym(RTLD_DEFAULT, "_dyld_register_func_for_add_image")
|
|
expectNotNil(_dyld_register_func_for_add_image_ptr)
|
|
|
|
typealias _dyld_register_func_for_add_image_func =
|
|
@convention(c) (add_image_callback) -> Void
|
|
let _dyld_register_func_for_add_image = unsafeBitCast(
|
|
_dyld_register_func_for_add_image_ptr,
|
|
to: _dyld_register_func_for_add_image_func.self)
|
|
_dyld_register_func_for_add_image(f)
|
|
}
|
|
|
|
// Make sure Swift doesn't register newly opened images before ObjC is ready
|
|
// for them to be used. rdar://problem/49742015
|
|
var add_image_count = 0
|
|
DlopenRaceTests.test("race") {
|
|
// This test is expected to fail unless the ObjC notification is supported.
|
|
let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: -2)
|
|
let objc_addLoadImageFunc = dlsym(RTLD_DEFAULT, "objc_addLoadImageFunc");
|
|
if objc_addLoadImageFunc == nil { return }
|
|
|
|
register_func_for_add_image({ header, slide in
|
|
// The protocol conformance check in the print call is enough to trigger
|
|
// ObjC class initialization in the newly opened image if Swift has
|
|
// registered the conformance records in that image. While we would be
|
|
// unlikely to make this sort of call directly in the callback in a real
|
|
// program, it could happen at this time in another thread.
|
|
print(header, slide)
|
|
add_image_count += 1
|
|
})
|
|
|
|
let dylibPath = CommandLine.arguments.last!
|
|
|
|
let beforeCount = add_image_count
|
|
let handle = dlopen(dylibPath, RTLD_LAZY)
|
|
expectNotNil(handle, String(cString: dlerror()))
|
|
expectEqual(add_image_count, beforeCount + 1)
|
|
}
|
|
|
|
runAllTests()
|