Don't use QSettings to "cache" plugin information
The main rationale of the cache was to examine the plugin's build-key before loading it. Now that the build-key has been removed, the cache has lost its usefulness. This is part of a larger push to not use QSettings for Qt specific settings or caches. See also: http://lists.qt.nokia.com/pipermail/qt5-feedback/2011-August/000892.html http://lists.qt.nokia.com/pipermail/qt5-feedback/2011-August/000960.html http://lists.qt.nokia.com/pipermail/qt5-feedback/2011-August/000907.html http://lists.qt.nokia.com/pipermail/qt5-feedback/2011-August/000904.html Change-Id: I96e84aa25983c8e06e027ff70cef109444c362a2 Reviewed-on: http://codereview.qt.nokia.com/3978 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Lars Knoll <lars.knoll@nokia.com>
This commit is contained in:
parent
6fd75df288
commit
8ed47d961d
@ -266,18 +266,6 @@ bool QCoreApplicationPrivate::is_app_closing = false;
|
||||
// initialized in qcoreapplication and in qtextstream autotest when setlocale is called.
|
||||
Q_CORE_EXPORT bool qt_locale_initialized = false;
|
||||
|
||||
|
||||
/*
|
||||
Create an instance of Trolltech.conf. This ensures that the settings will not
|
||||
be thrown out of QSetting's cache for unused settings.
|
||||
*/
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QSettings, staticTrolltechConf, (QSettings::UserScope, QLatin1String("Trolltech")))
|
||||
|
||||
QSettings *QCoreApplicationPrivate::trolltechConf()
|
||||
{
|
||||
return staticTrolltechConf();
|
||||
}
|
||||
|
||||
Q_CORE_EXPORT uint qGlobalPostedEventsCount()
|
||||
{
|
||||
QThreadData *currentThreadData = QThreadData::current();
|
||||
|
@ -139,7 +139,6 @@ public:
|
||||
static uint attribs;
|
||||
static inline bool testAttribute(uint flag) { return attribs & (1 << flag); }
|
||||
static int app_compile_version;
|
||||
static QSettings *trolltechConf();
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -45,7 +45,6 @@
|
||||
#include "qfactoryinterface.h"
|
||||
#include "qmap.h"
|
||||
#include <qdir.h>
|
||||
#include <qsettings.h>
|
||||
#include <qdebug.h>
|
||||
#include "qmutex.h"
|
||||
#include "qplugin.h"
|
||||
@ -107,7 +106,6 @@ void QFactoryLoader::update()
|
||||
#ifdef QT_SHARED
|
||||
Q_D(QFactoryLoader);
|
||||
QStringList paths = QCoreApplication::libraryPaths();
|
||||
QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
|
||||
for (int i = 0; i < paths.count(); ++i) {
|
||||
const QString &pluginDir = paths.at(i);
|
||||
// Already loaded, skip it...
|
||||
@ -127,7 +125,7 @@ void QFactoryLoader::update()
|
||||
qDebug() << "QFactoryLoader::QFactoryLoader() looking at" << fileName;
|
||||
}
|
||||
library = QLibraryPrivate::findOrCreate(QFileInfo(fileName).canonicalFilePath());
|
||||
if (!library->isPlugin(&settings)) {
|
||||
if (!library->isPlugin()) {
|
||||
if (qt_debug_component()) {
|
||||
qDebug() << library->errorString;
|
||||
qDebug() << " not a plugin";
|
||||
@ -135,45 +133,26 @@ void QFactoryLoader::update()
|
||||
library->release();
|
||||
continue;
|
||||
}
|
||||
QString regkey = QString::fromLatin1("Qt Factory Cache %1.%2/%3:/%4")
|
||||
.arg((QT_VERSION & 0xff0000) >> 16)
|
||||
.arg((QT_VERSION & 0xff00) >> 8)
|
||||
.arg(QLatin1String(d->iid))
|
||||
.arg(fileName);
|
||||
QStringList reg, keys;
|
||||
reg = settings.value(regkey).toStringList();
|
||||
if (reg.count() && library->lastModified == reg[0]) {
|
||||
keys = reg;
|
||||
keys.removeFirst();
|
||||
} else {
|
||||
if (!library->loadPlugin()) {
|
||||
if (qt_debug_component()) {
|
||||
qDebug() << library->errorString;
|
||||
qDebug() << " could not load";
|
||||
}
|
||||
library->release();
|
||||
continue;
|
||||
QStringList keys;
|
||||
if (!library->loadPlugin()) {
|
||||
if (qt_debug_component()) {
|
||||
qDebug() << library->errorString;
|
||||
qDebug() << " could not load";
|
||||
}
|
||||
QObject *instance = library->instance();
|
||||
if (!instance) {
|
||||
library->release();
|
||||
// ignore plugins that have a valid signature but cannot be loaded.
|
||||
continue;
|
||||
}
|
||||
QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instance);
|
||||
if (instance && factory && instance->qt_metacast(d->iid))
|
||||
keys = factory->keys();
|
||||
if (keys.isEmpty())
|
||||
library->unload();
|
||||
reg.clear();
|
||||
reg << library->lastModified;
|
||||
reg += keys;
|
||||
settings.setValue(regkey, reg);
|
||||
library->release();
|
||||
continue;
|
||||
}
|
||||
if (qt_debug_component()) {
|
||||
qDebug() << "keys" << keys;
|
||||
QObject *instance = library->instance();
|
||||
if (!instance) {
|
||||
library->release();
|
||||
// ignore plugins that have a valid signature but cannot be loaded.
|
||||
continue;
|
||||
}
|
||||
|
||||
QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instance);
|
||||
if (instance && factory && instance->qt_metacast(d->iid))
|
||||
keys = factory->keys();
|
||||
if (keys.isEmpty())
|
||||
library->unload();
|
||||
if (keys.isEmpty()) {
|
||||
library->release();
|
||||
continue;
|
||||
|
@ -50,8 +50,6 @@
|
||||
#include <qfileinfo.h>
|
||||
#include <qmutex.h>
|
||||
#include <qmap.h>
|
||||
#include <qsettings.h>
|
||||
#include <qdatetime.h>
|
||||
#include <private/qcoreapplication_p.h>
|
||||
#ifdef Q_OS_MAC
|
||||
# include <private/qcore_mac_p.h>
|
||||
@ -648,7 +646,7 @@ bool qt_get_verificationdata(QtPluginQueryVerificationDataFunction pfn, uint *qt
|
||||
return qt_parse_pattern(szData, qt_version, debug);
|
||||
}
|
||||
|
||||
bool QLibraryPrivate::isPlugin(QSettings *settings)
|
||||
bool QLibraryPrivate::isPlugin()
|
||||
{
|
||||
errorString.clear();
|
||||
if (pluginState != MightBeAPlugin)
|
||||
@ -672,135 +670,88 @@ bool QLibraryPrivate::isPlugin(QSettings *settings)
|
||||
}
|
||||
#endif
|
||||
|
||||
QFileInfo fileinfo(fileName);
|
||||
|
||||
#ifndef QT_NO_DATESTRING
|
||||
lastModified = fileinfo.lastModified().toString(Qt::ISODate);
|
||||
#endif
|
||||
QString regkey = QString::fromLatin1("Qt Plugin Cache %1.%2.%3/%4")
|
||||
.arg((QT_VERSION & 0xff0000) >> 16)
|
||||
.arg((QT_VERSION & 0xff00) >> 8)
|
||||
.arg(QLIBRARY_AS_DEBUG ? QLatin1String("debug") : QLatin1String("false"))
|
||||
.arg(fileName);
|
||||
#ifdef Q_WS_MAC
|
||||
// On Mac, add the application arch to the reg key in order to
|
||||
// cache plugin information separately for each arch. This prevents
|
||||
// Qt from wrongly caching plugin load failures when the archs
|
||||
// don't match.
|
||||
#if defined(__x86_64__)
|
||||
regkey += QLatin1String("-x86_64");
|
||||
#elif defined(__i386__)
|
||||
regkey += QLatin1String("-i386");
|
||||
#elif defined(__ppc64__)
|
||||
regkey += QLatin1String("-ppc64");
|
||||
#elif defined(__ppc__)
|
||||
regkey += QLatin1String("-ppc");
|
||||
#endif
|
||||
#endif // Q_WS_MAC
|
||||
|
||||
QStringList reg;
|
||||
#ifndef QT_NO_SETTINGS
|
||||
if (!settings) {
|
||||
settings = QCoreApplicationPrivate::trolltechConf();
|
||||
}
|
||||
reg = settings->value(regkey).toStringList();
|
||||
#endif
|
||||
if (reg.count() == 3 && lastModified == reg.at(2)) {
|
||||
qt_version = reg.at(0).toUInt(0, 16);
|
||||
debug = bool(reg.at(1).toInt());
|
||||
success = qt_version != 0;
|
||||
} else {
|
||||
#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_SYMBIAN)
|
||||
if (!pHnd) {
|
||||
// use unix shortcut to avoid loading the library
|
||||
success = qt_unix_query(fileName, &qt_version, &debug, this);
|
||||
} else
|
||||
if (!pHnd) {
|
||||
// use unix shortcut to avoid loading the library
|
||||
success = qt_unix_query(fileName, &qt_version, &debug, this);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
bool retryLoadLibrary = false; // Only used on Windows with MS compiler.(false in other cases)
|
||||
do {
|
||||
bool temporary_load = false;
|
||||
{
|
||||
bool retryLoadLibrary = false; // Only used on Windows with MS compiler.(false in other cases)
|
||||
do {
|
||||
bool temporary_load = false;
|
||||
#ifdef Q_OS_WIN
|
||||
HMODULE hTempModule = 0;
|
||||
HMODULE hTempModule = 0;
|
||||
#endif
|
||||
if (!pHnd) {
|
||||
if (!pHnd) {
|
||||
#ifdef Q_OS_WIN
|
||||
DWORD dwFlags = (retryLoadLibrary) ? 0: DONT_RESOLVE_DLL_REFERENCES;
|
||||
//avoid 'Bad Image' message box
|
||||
UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
|
||||
hTempModule = ::LoadLibraryEx((wchar_t*)QDir::toNativeSeparators(fileName).utf16(), 0, dwFlags);
|
||||
SetErrorMode(oldmode);
|
||||
DWORD dwFlags = (retryLoadLibrary) ? 0: DONT_RESOLVE_DLL_REFERENCES;
|
||||
//avoid 'Bad Image' message box
|
||||
UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
|
||||
hTempModule = ::LoadLibraryEx((wchar_t*)QDir::toNativeSeparators(fileName).utf16(), 0, dwFlags);
|
||||
SetErrorMode(oldmode);
|
||||
#else
|
||||
# if defined(Q_OS_SYMBIAN)
|
||||
//Guard against accidentally trying to load non-plugin libraries by making sure the stub exists
|
||||
if (fileinfo.exists())
|
||||
//Guard against accidentally trying to load non-plugin libraries by making sure the stub exists
|
||||
if (fileinfo.exists())
|
||||
# endif
|
||||
temporary_load = load_sys();
|
||||
temporary_load = load_sys();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifdef Q_OS_WIN
|
||||
QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = hTempModule ? (QtPluginQueryVerificationDataFunction)
|
||||
QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = hTempModule ? (QtPluginQueryVerificationDataFunction)
|
||||
#ifdef Q_OS_WINCE
|
||||
::GetProcAddress(hTempModule, L"qt_plugin_query_verification_data")
|
||||
::GetProcAddress(hTempModule, L"qt_plugin_query_verification_data")
|
||||
#else
|
||||
::GetProcAddress(hTempModule, "qt_plugin_query_verification_data")
|
||||
::GetProcAddress(hTempModule, "qt_plugin_query_verification_data")
|
||||
#endif
|
||||
: (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data");
|
||||
: (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data");
|
||||
#else
|
||||
QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = NULL;
|
||||
QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = NULL;
|
||||
# if defined(Q_OS_SYMBIAN)
|
||||
if (temporary_load) {
|
||||
qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data");
|
||||
// If resolving with function name failed (i.e. not STDDLL), try resolving using known ordinal
|
||||
if (!qtPluginQueryVerificationDataFunction)
|
||||
qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("1");
|
||||
}
|
||||
# else
|
||||
if (temporary_load) {
|
||||
qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data");
|
||||
// If resolving with function name failed (i.e. not STDDLL), try resolving using known ordinal
|
||||
if (!qtPluginQueryVerificationDataFunction)
|
||||
qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("1");
|
||||
}
|
||||
# else
|
||||
qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data");
|
||||
# endif
|
||||
#endif
|
||||
bool exceptionThrown = false;
|
||||
bool ret = qt_get_verificationdata(qtPluginQueryVerificationDataFunction,
|
||||
&qt_version, &debug, &exceptionThrown);
|
||||
if (!exceptionThrown) {
|
||||
if (!ret) {
|
||||
qt_version = 0;
|
||||
if (temporary_load)
|
||||
unload_sys();
|
||||
} else {
|
||||
success = true;
|
||||
}
|
||||
retryLoadLibrary = false;
|
||||
bool exceptionThrown = false;
|
||||
bool ret = qt_get_verificationdata(qtPluginQueryVerificationDataFunction,
|
||||
&qt_version, &debug, &exceptionThrown);
|
||||
if (!exceptionThrown) {
|
||||
if (!ret) {
|
||||
qt_version = 0;
|
||||
if (temporary_load)
|
||||
unload_sys();
|
||||
} else {
|
||||
success = true;
|
||||
}
|
||||
retryLoadLibrary = false;
|
||||
}
|
||||
#ifdef QT_USE_MS_STD_EXCEPTION
|
||||
else {
|
||||
// An exception was thrown when calling qt_plugin_query_verification_data().
|
||||
// This usually happens when plugin is compiled with the /clr compiler flag,
|
||||
// & will only work if the dependencies are loaded & DLLMain() is called.
|
||||
// LoadLibrary() will do this, try once with this & if it fails dont load.
|
||||
retryLoadLibrary = !retryLoadLibrary;
|
||||
}
|
||||
else {
|
||||
// An exception was thrown when calling qt_plugin_query_verification_data().
|
||||
// This usually happens when plugin is compiled with the /clr compiler flag,
|
||||
// & will only work if the dependencies are loaded & DLLMain() is called.
|
||||
// LoadLibrary() will do this, try once with this & if it fails dont load.
|
||||
retryLoadLibrary = !retryLoadLibrary;
|
||||
}
|
||||
#endif
|
||||
#ifdef Q_OS_WIN
|
||||
if (hTempModule) {
|
||||
BOOL ok = ::FreeLibrary(hTempModule);
|
||||
if (ok) {
|
||||
hTempModule = 0;
|
||||
}
|
||||
|
||||
if (hTempModule) {
|
||||
BOOL ok = ::FreeLibrary(hTempModule);
|
||||
if (ok) {
|
||||
hTempModule = 0;
|
||||
}
|
||||
#endif
|
||||
} while(retryLoadLibrary); // Will be 'false' in all cases other than when an
|
||||
// exception is thrown(will happen only when using a MS compiler)
|
||||
}
|
||||
|
||||
#ifndef QT_NO_SETTINGS
|
||||
QStringList queried;
|
||||
queried << QString::number(qt_version,16)
|
||||
<< QString::number((int)debug)
|
||||
<< lastModified;
|
||||
settings->setValue(regkey, queried);
|
||||
}
|
||||
#endif
|
||||
} while (retryLoadLibrary); // Will be 'false' in all cases other than when an
|
||||
// exception is thrown(will happen only when using a MS compiler)
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
|
@ -68,7 +68,6 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
bool qt_debug_component();
|
||||
|
||||
class QSettings;
|
||||
class QLibraryPrivate
|
||||
{
|
||||
public:
|
||||
@ -99,7 +98,7 @@ public:
|
||||
QString errorString;
|
||||
QLibrary::LoadHints loadHints;
|
||||
|
||||
bool isPlugin(QSettings *settings = 0);
|
||||
bool isPlugin();
|
||||
|
||||
|
||||
private:
|
||||
|
@ -98,22 +98,6 @@ QT_BEGIN_NAMESPACE
|
||||
every instance has called unload(). Right before the unloading
|
||||
happen, the root component will also be deleted.
|
||||
|
||||
In order to speed up loading and validation of plugins, some of
|
||||
the information that is collected during loading is cached in
|
||||
persistent memory (through QSettings). For instance, the result
|
||||
of a load operation (e.g. succeeded or failed) is stored in the
|
||||
cache, so that subsequent load operations don't try to load an
|
||||
invalid plugin. However, if the "last modified" timestamp of
|
||||
a plugin has changed, the plugin's cache entry is invalidated
|
||||
and the plugin is reloaded regardless of the values in the cache
|
||||
entry. The cache entry is then updated with the new result of the
|
||||
load operation.
|
||||
|
||||
This also means that the timestamp must be updated each time the
|
||||
plugin or any dependent resources (such as a shared library) is
|
||||
updated, since the dependent resources might influence the result
|
||||
of loading a plugin.
|
||||
|
||||
See \l{How to Create Qt Plugins} for more information about
|
||||
how to make your application extensible through plugins.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user