File: dlopen_race.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (57 lines) | stat: -rw-r--r-- 2,254 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// 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()