Skip to content

Commit f50ba81

Browse files
authored
Merge pull request #22126 from aschwaighofer/dynamic_replacement_workaround_5.0
[5.0] DynamicReplacement: Don't fail when a library is closed and reloaded
2 parents 942b055 + bf92739 commit f50ba81

File tree

4 files changed

+91
-0
lines changed

4 files changed

+91
-0
lines changed

stdlib/public/runtime/MetadataLookup.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1677,11 +1677,15 @@ void DynamicReplacementDescriptor::enableReplacement() const {
16771677
replacedFunctionKey->root.get());
16781678

16791679
// Make sure this entry is not already enabled.
1680+
// This does not work until we make sure that when a dynamic library is
1681+
// unloaded all descriptors are removed.
1682+
#if 0
16801683
for (auto *curr = chainRoot; curr != nullptr; curr = curr->next) {
16811684
if (curr == chainEntry.get()) {
16821685
swift::swift_abortDynamicReplacementEnabling();
16831686
}
16841687
}
1688+
#endif
16851689

16861690
// Unlink the previous entry if we are not chaining.
16871691
if (!shouldChain() && chainRoot->next) {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
struct A {
2+
dynamic var value : Int {
3+
return 1
4+
}
5+
}
6+
7+
public func test() -> Int{
8+
return A().value
9+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
@_private(sourceFile: "dynamic_replacement_dlclose.swift") import Module1
2+
3+
extension A {
4+
@_dynamicReplacement(for: value)
5+
var repl: Int {
6+
return 2
7+
}
8+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift-dylib(%t/libModule1.%target-dylib-extension) -DMODULE -module-name Module1 -emit-module -emit-module-path %t/Module1.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_dlclose.swift -Xfrontend -enable-private-imports
3+
// RUN: %target-build-swift-dylib(%t/libModule2.%target-dylib-extension) -I%t -L%t -lModule1 -Xlinker -rpath -Xlinker %t -DMODULE2 -module-name Module2 -emit-module -emit-module-path %t/Module2.swiftmodule -swift-version 5 %S/Inputs/dynamic_replacement_dlclose2.swift
4+
// RUN: %target-build-swift -I%t -L%t -lModule1 -DMAIN -o %t/main -Xlinker -rpath -Xlinker %t %s -swift-version 5
5+
// RUN: %target-codesign %t/main %t/libModule1.%target-dylib-extension %t/libModule2.%target-dylib-extension
6+
// RUN: %target-run %t/main %t/libModule1.%target-dylib-extension %t/libModule2.%target-dylib-extension
7+
8+
9+
import Module1
10+
11+
import StdlibUnittest
12+
13+
#if os(Linux)
14+
import Glibc
15+
#elseif os(Windows)
16+
import MSVCRT
17+
import WinSDK
18+
#else
19+
import Darwin
20+
#endif
21+
22+
var DynamicallyReplaceable = TestSuite("DynamicallyReplaceable")
23+
24+
25+
26+
private func target_library_name(_ name: String) -> String {
27+
#if os(iOS) || os(macOS) || os(tvOS) || os(watchOS)
28+
return "lib\(name).dylib"
29+
#elseif os(Windows)
30+
return "\(name).dll"
31+
#else
32+
return "lib\(name).so"
33+
#endif
34+
}
35+
36+
37+
DynamicallyReplaceable.test("DynamicallyReplaceable") {
38+
var executablePath = CommandLine.arguments[0]
39+
executablePath.removeLast(4)
40+
expectEqual(1, test())
41+
// Now, test with the module containing the replacements.
42+
43+
#if os(Linux)
44+
let h = dlopen(target_library_name("Module2"), RTLD_NOW)
45+
#elseif os(Windows)
46+
let h = LoadLibraryA(target_library_name("Module2"))
47+
#else
48+
let h = dlopen(executablePath+target_library_name("Module2"), RTLD_NOW)
49+
#endif
50+
51+
expectEqual(2, test())
52+
53+
#if os(Linux)
54+
dlclose(h!)
55+
#elseif os(Windows)
56+
#else
57+
dlclose(h)
58+
#endif
59+
60+
#if os(Linux)
61+
_ = dlopen(target_library_name("Module2"), RTLD_NOW)
62+
#elseif os(Windows)
63+
#else
64+
_ = dlopen(executablePath+target_library_name("Module2"), RTLD_NOW)
65+
#endif
66+
expectEqual(2, test())
67+
68+
}
69+
70+
runAllTests()

0 commit comments

Comments
 (0)