// 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()