summaryrefslogtreecommitdiffstats
path: root/src/corelib/plugin
diff options
context:
space:
mode:
authorThiago Macieira <[email protected]>2025-03-24 22:14:32 -0700
committerThiago Macieira <[email protected]>2025-05-25 16:58:27 +0000
commit1a54a0330141ea01fa9b81c8deb23f063815ce8f (patch)
tree51e66267163b705f5a31a87fafabec8d25255562 /src/corelib/plugin
parent0c0b5d0ff09ff21d3d8b11bbc3797596450f2882 (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.cpp6
-rw-r--r--src/corelib/plugin/qfactoryloader_p.h2
-rw-r--r--src/corelib/plugin/qlibrary_unix.cpp5
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