diff options
author | Thiago Macieira <[email protected]> | 2025-03-24 22:14:32 -0700 |
---|---|---|
committer | Thiago Macieira <[email protected]> | 2025-05-25 16:58:27 +0000 |
commit | 1a54a0330141ea01fa9b81c8deb23f063815ce8f (patch) | |
tree | 51e66267163b705f5a31a87fafabec8d25255562 /src/corelib/plugin | |
parent | 0c0b5d0ff09ff21d3d8b11bbc3797596450f2882 (diff) |
QLibrary/Darwin: don't use RTLD_NODELETE, just don't dlclose()
As the comment says, the OS does support the flag and a perusal of the
source code for dyld[1] shows it does handle the flag, setting an
internal flag called "leaveMapped", which is different from the
"neverUnload" flag. My guess is that it literally just leaves the memory
for the plugin mapped, but removes all links to it in the dyld internal
data structures.
That results in the Objective C runtime crashing when running content
from NODELETE plugins that has been dlclose()d. This probably explains
why lldb stops seeing those symbols too:
(lldb) f
frame #0: 0x0000000103872eb4 QtCore`QLibraryPrivate::unload_sys(this=0x000060000179c210) at qlibrary_unix.cpp:258:21
-> 258 if (doTryUnload && dlclose(pHnd.loadAcquire())) {
(lldb) target modules list libqcocoa.dylib
[ 0] 81EB58D5-8D31-333A-9E8C-F2385F6EFCF4 0x00000001043de000 libqcocoa.dylib
(lldb) image lookup -vn QCocoaEventDispatcher::QCocoaEventDispatcher
2 matches found in libqcocoa.dylib:
Address: libqcocoa.dylib[0x0000000000036480] (libqcocoa.dylib.__TEXT.__text + 190368)
Summary: libqcocoa.dylib`QCocoaEventDispatcher::QCocoaEventDispatcher(QObject*) at qcocoaeventdispatcher.mm:776
...
(lldb) n
(lldb) target modules list libqcocoa.dylib
[ 0] 81EB58D5-8D31-333A-9E8C-F2385F6EFCF4 libqcocoa.dylib[0x0000000000000000] libqcocoa.dylib
(lldb) image lookup -vn QCocoaEventDispatcher::QCocoaEventDispatcher
[1] https://github.com/apple-oss-distributions/dyld
Task-number: QTBUG-135044
Task-number: QTBUG-134080
Task-number: QTBUG-133861
Task-number: QTBUG-132697
Task-number: QTBUG-102984
Task-number: QTBUG-132381
Pick-to: 6.9 6.9.0 6.8
Change-Id: I7da3b3615a6ace7c72d1fffd5cf560d8f8a4e1bb
Reviewed-by: Tor Arne Vestbø <[email protected]>
Diffstat (limited to 'src/corelib/plugin')
-rw-r--r-- | src/corelib/plugin/qfactoryloader.cpp | 6 | ||||
-rw-r--r-- | src/corelib/plugin/qfactoryloader_p.h | 2 | ||||
-rw-r--r-- | src/corelib/plugin/qlibrary_unix.cpp | 5 |
3 files changed, 13 insertions, 0 deletions
diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp index 21e4c294c91..31abed73cf9 100644 --- a/src/corelib/plugin/qfactoryloader.cpp +++ b/src/corelib/plugin/qfactoryloader.cpp @@ -359,6 +359,11 @@ inline void QFactoryLoader::Private::updateSinglePath(const QString &path) loadedLibraries.resize(libraries.size()); } +void QFactoryLoader::setLoadHints(QLibrary::LoadHints loadHints) +{ + d->loadHints = loadHints; +} + void QFactoryLoader::update() { #ifdef QT_SHARED @@ -549,6 +554,7 @@ inline QObject *QFactoryLoader::instanceHelper_locked(int index) const if (size_t(index) < d->libraries.size()) { QLibraryPrivate *library = d->libraries[index].get(); d->loadedLibraries[index] = true; + library->setLoadHints(d->loadHints); return library->pluginInstance(); } // we know d->libraries.size() <= index <= numeric_limits<decltype(index)>::max() → no overflow diff --git a/src/corelib/plugin/qfactoryloader_p.h b/src/corelib/plugin/qfactoryloader_p.h index c14e5795a8f..d7482b36198 100644 --- a/src/corelib/plugin/qfactoryloader_p.h +++ b/src/corelib/plugin/qfactoryloader_p.h @@ -48,6 +48,7 @@ public: #if QT_CONFIG(library) ~QFactoryLoader(); + void setLoadHints(QLibrary::LoadHints hints); void update(); static void refreshAll(); @@ -79,6 +80,7 @@ private: QString suffix; QString extraSearchPath; Qt::CaseSensitivity cs; + QLibrary::LoadHints loadHints; void updateSinglePath(const QString &pluginDir); #endif diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp index e629e2b1f12..f03eba3bffa 100644 --- a/src/corelib/plugin/qlibrary_unix.cpp +++ b/src/corelib/plugin/qlibrary_unix.cpp @@ -14,6 +14,11 @@ #ifdef Q_OS_DARWIN # include <private/qcore_mac_p.h> + +// Apple's dyld *does* support RTLD_NODELETE and the library remains loaded in +// memory after the dlclose() call, but their Objective C crashes when running +// code from unloaded-but-still-loaded plugins. +# undef RTLD_NODELETE #endif #ifdef Q_OS_ANDROID |