Skip to content

Commit 2efb4f8

Browse files
authored
Merge pull request #1257 from NativeScript/bektchiev/fix-symbol-loader
fix(runtime): Unload frameworks in SymbolLoader::load
2 parents 62f818d + 9796e38 commit 2efb4f8

File tree

2 files changed

+37
-5
lines changed

2 files changed

+37
-5
lines changed

src/NativeScript/SymbolLoader.mm

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
class CFBundleSymbolResolver : public SymbolResolver {
2525
public:
2626
CFBundleSymbolResolver(WTF::RetainPtr<CFBundleRef> bundle)
27-
: _bundle(bundle) {
27+
: _bundle(bundle)
28+
, _loaded(false) {
2829
}
2930

3031
virtual void* loadFunctionSymbol(const char* symbolName) override {
@@ -38,17 +39,47 @@
3839
}
3940

4041
virtual bool load() override {
41-
CFErrorRef error = nullptr;
42-
bool loaded = CFBundleLoadExecutableAndReturnError(this->_bundle.get(), &error);
42+
if (this->_loaded) {
43+
return true;
44+
}
45+
46+
// Use NSBundle for loading because of the following statement in the docs:
47+
// For most of its methods, NSBundle simply calls the appropriate CFBundle routine to do its work,
48+
// but loading code is different. Because CFBundle does not handle Objective-C symbols, NSBundle has
49+
// to use a different mechanism for loading code. NSBundle interacts with the Objective-C runtime
50+
// system to correctly load and register all Cocoa classes and other executable code in the bundle
51+
// executable file.
52+
// See https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/LoadingCode/Concepts/CFNSBundle.html
53+
54+
NSURL* url = (__bridge NSURL*)CFBundleCopyBundleURL(this->_bundle.get());
55+
NSBundle* bundle = [NSBundle bundleWithURL:url];
56+
[url release];
57+
58+
bool wasLoaded = bundle.loaded;
59+
NSError* error = nullptr;
60+
bool loaded = [bundle loadAndReturnError:&error];
61+
62+
if (loaded) {
63+
this->_loaded = true;
64+
if (!wasLoaded) {
65+
// Unload the bundle if it was not previously loaded. Sometimes framework bundles use
66+
// resource bundles of the same name and keeping the framework loaded as a bundle
67+
// breaks them. OTH, loading and unloading a framework bundle is sufficient for its
68+
// executable code to be registered with the Objective-C runtime.
69+
[bundle unload];
70+
}
71+
}
72+
4373
if (error) {
44-
dataLogF("%s\n", [[(NSError*)error localizedDescription] UTF8String]);
74+
dataLogF("%s\n", [[error localizedDescription] UTF8String]);
4575
}
4676

4777
return loaded;
4878
}
4979

5080
private:
5181
WTF::RetainPtr<CFBundleRef> _bundle;
82+
bool _loaded;
5283
};
5384

5485
class DlSymbolResolver : public SymbolResolver {

tests/TestRunner/app/ApiTests.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -817,7 +817,8 @@ describe(module.id, function () {
817817
// according to SDK headers kCFAllocatorUseContext is of type id, but in fact it is not
818818
if (name == "kCFAllocatorUseContext" ||
819819
name == "JSExport" ||
820-
name == "kSCNetworkInterfaceIPv4") {
820+
name == "kSCNetworkInterfaceIPv4" ||
821+
name == "getBlacklistedRusage_info_v0") {
821822
return;
822823
}
823824

0 commit comments

Comments
 (0)