summaryrefslogtreecommitdiffstats
path: root/src/corelib/plugin
diff options
context:
space:
mode:
authorSean Harmer <sean.harmer@kdab.com>2012-07-18 16:06:06 +0100
committerQt by Nokia <qt-info@nokia.com>2012-07-27 18:07:01 +0200
commit2f4093332db6c9057b82f9c5fababc9bc6cbeb32 (patch)
treece8a47a14d22f70796ec78dc7d90ed7742dd134c /src/corelib/plugin
parentcc9020490ac5e0fba580f73ca8b9948a1b4b54bf (diff)
Introduce ImprovedSearchHeuristics flag to QLibrary
This commit introduces a new flag to safely introduce the improved search behaviour in Qt5's QLibrary. If the flag is set then QLibrary will use the following search heuristic. Otherwise the existing behaviour will be used. New search behaviour: If an absolute path is specified we try that first. Otherwise we first try the most likely system-specific format (e.g. libfoo.so) on Unix. This improves performance especially on systems with slow flash devices. For example, prior to this commit loading the Xcursor library (in the xcb plugin) results in attempts to dlopen: "Xcursor" "Xcursor.so.1" "libXcursor" "libXcursor.so.1" With this commit this is reduced to a single attempt of: "libXcursor.so.1" Plugin loading uses absolute paths with QLibrary so there is no performance penalty for plugins with this commit. There will be a follow-up commit to make use of the new flag within Qt to improve performance. This is a backport of 0026b80cd2a484ad9d685ff5a4f89e6c9815f913 Change-Id: I0dbc83c2909713c01dc687ab8cc3cb0619d1500a Reviewed-by: Lars Knoll <lars.knoll@nokia.com>
Diffstat (limited to 'src/corelib/plugin')
-rw-r--r--src/corelib/plugin/qlibrary.h3
-rw-r--r--src/corelib/plugin/qlibrary_unix.cpp23
-rw-r--r--src/corelib/plugin/qlibrary_win.cpp91
3 files changed, 92 insertions, 25 deletions
diff --git a/src/corelib/plugin/qlibrary.h b/src/corelib/plugin/qlibrary.h
index c77533f188..101df746e1 100644
--- a/src/corelib/plugin/qlibrary.h
+++ b/src/corelib/plugin/qlibrary.h
@@ -69,7 +69,8 @@ public:
enum LoadHint {
ResolveAllSymbolsHint = 0x01,
ExportExternalSymbolsHint = 0x02,
- LoadArchiveMemberHint = 0x04
+ LoadArchiveMemberHint = 0x04,
+ ImprovedSearchHeuristics = 0x08
};
Q_DECLARE_FLAGS(LoadHints, LoadHint)
diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp
index 1d0f32257a..74cf9a8089 100644
--- a/src/corelib/plugin/qlibrary_unix.cpp
+++ b/src/corelib/plugin/qlibrary_unix.cpp
@@ -103,9 +103,9 @@ bool QLibraryPrivate::load_sys()
else
path += QLatin1Char('/');
#endif
- // The first filename we want to attempt to load is the filename as the callee specified.
- // Thus, the first attempt we do must be with an empty prefix and empty suffix.
- QStringList suffixes(QLatin1String("")), prefixes(QLatin1String(""));
+
+ QStringList suffixes;
+ QStringList prefixes;
if (pluginState != IsAPlugin) {
#if !defined(Q_OS_SYMBIAN)
prefixes << QLatin1String("lib");
@@ -187,6 +187,23 @@ bool QLibraryPrivate::load_sys()
}
#endif
#endif // QT_HPUX_LD
+ // If using the new search heuristics we do:
+ //
+ // If the filename is an absolute path then we want to try that first as it is most likely
+ // what the callee wants. If we have been given a non-absolute path then lets try the
+ // native library name first to avoid unnecessary calls to dlopen().
+ //
+ // otherwise:
+ //
+ // We use the old behaviour which is to always try the specified filename first
+ if ((loadHints & QLibrary::ImprovedSearchHeuristics) && !fsEntry.isAbsolute()) {
+ suffixes.append(QLatin1String(""));
+ prefixes.append(QLatin1String(""));
+ } else {
+ suffixes.prepend(QLatin1String(""));
+ prefixes.prepend(QLatin1String(""));
+ }
+
bool retry = true;
for(int prefix = 0; retry && !pHnd && prefix < prefixes.size(); prefix++) {
for(int suffix = 0; retry && !pHnd && suffix < suffixes.size(); suffix++) {
diff --git a/src/corelib/plugin/qlibrary_win.cpp b/src/corelib/plugin/qlibrary_win.cpp
index 0c450e3ee7..2c09f6f722 100644
--- a/src/corelib/plugin/qlibrary_win.cpp
+++ b/src/corelib/plugin/qlibrary_win.cpp
@@ -45,6 +45,7 @@
#include "qdir.h"
#include "qfileinfo.h"
#include "qdir.h"
+#include <private/qfilesystementry_p.h>
#if defined(QT_NO_LIBRARY) && defined(Q_OS_WIN)
#undef QT_NO_LIBRARY
@@ -59,46 +60,94 @@ extern QString qt_error_string(int code);
bool QLibraryPrivate::load_sys()
{
-#ifdef Q_OS_WINCE
- QString attempt = QFileInfo(fileName).absoluteFilePath();
-#else
- QString attempt = fileName;
-#endif
-
//avoid 'Bad Image' message box
UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
- pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(attempt).utf16());
- if (pluginState != IsAPlugin) {
+ // We make the following attempts at locating the library:
+ //
+ // WinCE
+ // if (loadHints & QLibrary::ImprovedSearchHeuristics)
+ // if (absolute)
+ // fileName
+ // fileName + ".dll"
+ // else
+ // fileName + ".dll"
+ // fileName
+ // QFileInfo(fileName).absoluteFilePath()
+ // else
+ // QFileInfo(fileName).absoluteFilePath();
+ // fileName
+ // fileName + ".dll"
+ //
+ // Windows
+ // if (loadHints & QLibrary::ImprovedSearchHeuristics)
+ // if (absolute)
+ // fileName
+ // fileName + ".dll"
+ // else
+ // fileName + ".dll"
+ // fileName
+ // else
+ // fileName
+ // fileName + ".dll"
+ //
+ // NB If it's a plugin we do not ever try the ".dll" extension
+ QStringList attempts;
+ QFileSystemEntry fsEntry(fileName);
+ if (loadHints & QLibrary::ImprovedSearchHeuristics) {
+ if (pluginState != IsAPlugin)
+ attempts.append(fileName + QLatin1String(".dll"));
+
+ // If the fileName is an absolute path we try that first, otherwise we
+ // use the system-specific suffix first
+ if (fsEntry.isAbsolute()) {
+ attempts.prepend(fileName);
+ } else {
+ attempts.append(fileName);
#if defined(Q_OS_WINCE)
- if (!pHnd && ::GetLastError() == ERROR_MOD_NOT_FOUND) {
- QString secondAttempt = fileName;
- pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(secondAttempt).utf16());
+ attempts.append(QFileInfo(fileName).absoluteFilePath());
+#endif
}
+ } else {
+#ifdef Q_OS_WINCE
+ attempts.append(QFileInfo(fileName).absoluteFilePath());
+#else
+ attempts.append(fileName);
+#endif
+ if (pluginState != IsAPlugin) {
+#if defined(Q_OS_WINCE)
+ attempts.append(fileName);
#endif
- if (!pHnd && ::GetLastError() == ERROR_MOD_NOT_FOUND) {
- attempt += QLatin1String(".dll");
- pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(attempt).utf16());
+ attempts.append(fileName + QLatin1String(".dll"));
}
}
+ Q_FOREACH (const QString &attempt, attempts) {
+ pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(attempt).utf16());
+
+ // If we have a handle or the last error is something other than "unable
+ // to find the module", then bail out
+ if (pHnd || ::GetLastError() != ERROR_MOD_NOT_FOUND)
+ break;
+ }
+
SetErrorMode(oldmode);
if (!pHnd) {
errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName).arg(qt_error_string());
- }
- if (pHnd) {
+ } else {
+ // Query the actual name of the library that was loaded
errorString.clear();
wchar_t buffer[MAX_PATH];
::GetModuleFileName(pHnd, buffer, MAX_PATH);
- attempt = QString::fromWCharArray(buffer);
- const QDir dir = QFileInfo(fileName).dir();
- const QString realfilename = attempt.mid(attempt.lastIndexOf(QLatin1Char('\\')) + 1);
+ QString moduleFileName = QString::fromWCharArray(buffer);
+ moduleFileName.remove(0, 1 + moduleFileName.lastIndexOf(QLatin1Char('\\')));
+ const QDir dir(fsEntry.path());
if (dir.path() == QLatin1String("."))
- qualifiedFileName = realfilename;
+ qualifiedFileName = moduleFileName;
else
- qualifiedFileName = dir.filePath(realfilename);
+ qualifiedFileName = dir.filePath(moduleFileName);
}
return (pHnd != 0);
}