diff options
author | Oswald Buddenhagen <oswald.buddenhagen@digia.com> | 2013-03-20 13:46:57 +0100 |
---|---|---|
committer | Oswald Buddenhagen <oswald.buddenhagen@digia.com> | 2013-03-20 13:49:28 +0100 |
commit | 76c0be34cd4ff4564693162fa7528463e23ce9d8 (patch) | |
tree | f165b7bc319548fb0082365411a871028f92e89e /src/corelib/plugin | |
parent | 27b4fe96b59e9e63d1e570e802c072e9afdfb2d4 (diff) | |
parent | 36cb3f3f655a9090c82de609010cbfb88651a0f3 (diff) |
Merge branch 'dev' into stable
This starts Qt 5.1 release cycle
Conflicts:
src/gui/text/qfontdatabase.cpp
src/gui/text/qharfbuzz_copy_p.h
src/widgets/kernel/qapplication.cpp
src/widgets/kernel/qcoreapplication.cpp
Change-Id: I72fbf83ab3c2206aeea1b089428b0fc2a89bd62b
Diffstat (limited to 'src/corelib/plugin')
-rw-r--r-- | src/corelib/plugin/qfactoryinterface.h | 4 | ||||
-rw-r--r-- | src/corelib/plugin/qlibrary.cpp | 173 | ||||
-rw-r--r-- | src/corelib/plugin/qlibrary.h | 10 | ||||
-rw-r--r-- | src/corelib/plugin/qlibrary_p.h | 9 | ||||
-rw-r--r-- | src/corelib/plugin/qlibrary_unix.cpp | 2 | ||||
-rw-r--r-- | src/corelib/plugin/qlibrary_win.cpp | 7 | ||||
-rw-r--r-- | src/corelib/plugin/qplugin.h | 4 | ||||
-rw-r--r-- | src/corelib/plugin/qpluginloader.h | 9 | ||||
-rw-r--r-- | src/corelib/plugin/quuid.cpp | 12 | ||||
-rw-r--r-- | src/corelib/plugin/quuid.h | 4 |
10 files changed, 143 insertions, 91 deletions
diff --git a/src/corelib/plugin/qfactoryinterface.h b/src/corelib/plugin/qfactoryinterface.h index 59bce69022..88fb1bf599 100644 --- a/src/corelib/plugin/qfactoryinterface.h +++ b/src/corelib/plugin/qfactoryinterface.h @@ -45,8 +45,6 @@ #include <QtCore/qobject.h> #include <QtCore/qstringlist.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -61,6 +59,4 @@ Q_DECLARE_INTERFACE(QFactoryInterface, "org.qt-project.Qt.QFactoryInterface") QT_END_NAMESPACE -QT_END_HEADER - #endif // QFACTORYINTERFACE_H diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp index d17067684a..3432f9619d 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -79,8 +79,6 @@ QT_BEGIN_NAMESPACE # define QT_NO_DEBUG_PLUGIN_CHECK #endif -static QBasicMutex qt_library_mutex; - /*! \class QLibrary \inmodule QtCore @@ -339,46 +337,134 @@ static void installCoverageTool(QLibraryPrivate *libPrivate) #endif } -typedef QMap<QString, QLibraryPrivate*> LibraryMap; +class QLibraryStore +{ +public: + inline ~QLibraryStore(); + static inline QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version); + static inline void releaseLibrary(QLibraryPrivate *lib); + + static inline void cleanup(); -struct LibraryData { +private: + static inline QLibraryStore *instance(); + + // all members and instance() are protected by qt_library_mutex + typedef QMap<QString, QLibraryPrivate*> LibraryMap; LibraryMap libraryMap; - QSet<QLibraryPrivate*> loadedLibs; }; -Q_GLOBAL_STATIC(LibraryData, libraryData) +static QBasicMutex qt_library_mutex; +static QLibraryStore *qt_library_data = 0; + +QLibraryStore::~QLibraryStore() +{ + qt_library_data = 0; +} + +inline void QLibraryStore::cleanup() +{ + QLibraryStore *data = qt_library_data; + if (!data) + return; + + // find any libraries that are still loaded but have a no one attached to them + LibraryMap::Iterator it = data->libraryMap.begin(); + for (; it != data->libraryMap.end(); ++it) { + QLibraryPrivate *lib = it.value(); + if (lib->libraryRefCount.load() == 1) { + if (lib->libraryUnloadCount.load() > 0) { + Q_ASSERT(lib->pHnd); + lib->libraryUnloadCount.store(1); +#ifdef __GLIBC__ + // glibc has a bug in unloading from global destructors + // see https://bugzilla.novell.com/show_bug.cgi?id=622977 + // and http://sourceware.org/bugzilla/show_bug.cgi?id=11941 + lib->unload(QLibraryPrivate::NoUnloadSys); +#else + lib->unload(); +#endif + } + delete lib; + it.value() = 0; + } + } + + if (qt_debug_component()) { + // dump all objects that remain + foreach (QLibraryPrivate *lib, data->libraryMap) { + if (lib) + qDebug() << "On QtCore unload," << lib->fileName << "was leaked, with" + << lib->libraryRefCount.load() << "users"; + } + } + + delete data; +} + +static void qlibraryCleanup() +{ + QLibraryStore::cleanup(); +} +Q_DESTRUCTOR_FUNCTION(qlibraryCleanup) + +// must be called with a locked mutex +QLibraryStore *QLibraryStore::instance() +{ + if (Q_UNLIKELY(!qt_library_data)) + qt_library_data = new QLibraryStore; + return qt_library_data; +} -static LibraryMap *libraryMap() +inline QLibraryPrivate *QLibraryStore::findOrCreate(const QString &fileName, const QString &version) { - LibraryData *data = libraryData(); - return data ? &data->libraryMap : 0; + QMutexLocker locker(&qt_library_mutex); + QLibraryStore *data = instance(); + + // check if this library is already loaded + QLibraryPrivate *lib = data->libraryMap.value(fileName); + if (!lib) + lib = new QLibraryPrivate(fileName, version); + + // track this library + data->libraryMap.insert(fileName, lib); + + lib->libraryRefCount.ref(); + return lib; +} + +inline void QLibraryStore::releaseLibrary(QLibraryPrivate *lib) +{ + QMutexLocker locker(&qt_library_mutex); + QLibraryStore *data = instance(); + + if (lib->libraryRefCount.deref()) { + // still in use + return; + } + + // no one else is using + Q_ASSERT(lib->libraryUnloadCount.load() == 0); + + QLibraryPrivate *that = data->libraryMap.take(lib->fileName); + Q_ASSERT(lib == that); + Q_UNUSED(that); + delete lib; } QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version) : pHnd(0), fileName(canonicalFileName), fullVersion(version), instance(0), loadHints(0), - libraryRefCount(1), libraryUnloadCount(0), pluginState(MightBeAPlugin) -{ libraryMap()->insert(canonicalFileName, this); } + libraryRefCount(0), libraryUnloadCount(0), pluginState(MightBeAPlugin) +{ } QLibraryPrivate *QLibraryPrivate::findOrCreate(const QString &fileName, const QString &version) { - QMutexLocker locker(&qt_library_mutex); - if (QLibraryPrivate *lib = libraryMap()->value(fileName)) { - lib->libraryRefCount.ref(); - return lib; - } - - return new QLibraryPrivate(fileName, version); + return QLibraryStore::findOrCreate(fileName, version); } QLibraryPrivate::~QLibraryPrivate() { - LibraryMap * const map = libraryMap(); - if (map) { - QLibraryPrivate *that = map->take(fileName); - Q_ASSERT(this == that); - Q_UNUSED(that); - } } QFunctionPointer QLibraryPrivate::resolve(const char *symbol) @@ -391,9 +477,10 @@ QFunctionPointer QLibraryPrivate::resolve(const char *symbol) bool QLibraryPrivate::load() { - libraryUnloadCount.ref(); - if (pHnd) + if (pHnd) { + libraryUnloadCount.ref(); return true; + } if (fileName.isEmpty()) return false; @@ -403,32 +490,27 @@ bool QLibraryPrivate::load() if (ret) { //when loading a library we add a reference to it so that the QLibraryPrivate won't get deleted //this allows to unload the library at a later time - if (LibraryData *lib = libraryData()) { - lib->loadedLibs += this; - libraryRefCount.ref(); - } - + libraryUnloadCount.ref(); + libraryRefCount.ref(); installCoverageTool(this); } return ret; } -bool QLibraryPrivate::unload() +bool QLibraryPrivate::unload(UnloadFlag flag) { if (!pHnd) return false; - if (!libraryUnloadCount.deref()) { // only unload if ALL QLibrary instance wanted to + if (libraryUnloadCount.load() > 0 && !libraryUnloadCount.deref()) { // only unload if ALL QLibrary instance wanted to delete inst.data(); - if (unload_sys()) { + if (flag == NoUnloadSys || unload_sys()) { if (qt_debug_component()) - qWarning() << "QLibraryPrivate::unload succeeded on" << fileName; + qWarning() << "QLibraryPrivate::unload succeeded on" << fileName + << (flag == NoUnloadSys ? "(faked)" : ""); //when the library is unloaded, we release the reference on it so that 'this' //can get deleted - if (LibraryData *lib = libraryData()) { - if (lib->loadedLibs.remove(this)) - libraryRefCount.deref(); - } + libraryRefCount.deref(); pHnd = 0; instance = 0; } @@ -439,9 +521,7 @@ bool QLibraryPrivate::unload() void QLibraryPrivate::release() { - QMutexLocker locker(&qt_library_mutex); - if (!libraryRefCount.deref()) - delete this; + QLibraryStore::releaseLibrary(this); } bool QLibraryPrivate::loadPlugin() @@ -631,7 +711,7 @@ void QLibraryPrivate::updatePluginState() hTempModule = ::LoadLibraryEx((wchar_t*)QDir::toNativeSeparators(fileName).utf16(), 0, dwFlags); SetErrorMode(oldmode); #else - temporary_load = load_sys(); + temporary_load = load(); #endif } QtPluginQueryVerificationDataFunction getMetaData = NULL; @@ -656,11 +736,10 @@ void QLibraryPrivate::updatePluginState() if (getMetaData) ret = qt_get_metadata(getMetaData, this, &exceptionThrown); + if (temporary_load) + unload(); if (!exceptionThrown) { - if (!ret) { - if (temporary_load) - unload_sys(); - } else { + if (ret) { success = true; } retryLoadLibrary = false; diff --git a/src/corelib/plugin/qlibrary.h b/src/corelib/plugin/qlibrary.h index f99c69c2d7..865bb8c3e3 100644 --- a/src/corelib/plugin/qlibrary.h +++ b/src/corelib/plugin/qlibrary.h @@ -44,16 +44,8 @@ #include <QtCore/qobject.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE - -#if defined(QT_NO_LIBRARY) && defined(Q_OS_WIN) -#undef QT_NO_LIBRARY -#pragma message("QT_NO_LIBRARY is not supported on Windows") -#endif - #ifndef QT_NO_LIBRARY class QLibraryPrivate; @@ -111,6 +103,4 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QLibrary::LoadHints) QT_END_NAMESPACE -QT_END_HEADER - #endif //QLIBRARY_H diff --git a/src/corelib/plugin/qlibrary_p.h b/src/corelib/plugin/qlibrary_p.h index 28bec300eb..abf11be9f7 100644 --- a/src/corelib/plugin/qlibrary_p.h +++ b/src/corelib/plugin/qlibrary_p.h @@ -71,6 +71,7 @@ QT_BEGIN_NAMESPACE bool qt_debug_component(); +class QLibraryStore; class QLibraryPrivate { public: @@ -82,12 +83,14 @@ public: #endif pHnd; + enum UnloadFlag { UnloadSys, NoUnloadSys }; + QString fileName, qualifiedFileName; QString fullVersion; bool load(); bool loadPlugin(); // loads and resolves instance - bool unload(); + bool unload(UnloadFlag flag = UnloadSys); void release(); QFunctionPointer resolve(const char *); @@ -124,11 +127,13 @@ private: bool unload_sys(); QFunctionPointer resolve_sys(const char *); + /// counts how many QLibrary or QPluginLoader are attached to us, plus 1 if it's loaded QAtomicInt libraryRefCount; + /// counts how many times load() or loadPlugin() were called QAtomicInt libraryUnloadCount; enum { IsAPlugin, IsNotAPlugin, MightBeAPlugin } pluginState; - friend class QLibraryPrivateHasFriends; + friend class QLibraryStore; }; QT_END_NAMESPACE diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp index 5044d09e9b..2aed877e6b 100644 --- a/src/corelib/plugin/qlibrary_unix.cpp +++ b/src/corelib/plugin/qlibrary_unix.cpp @@ -56,7 +56,7 @@ #include <string.h> #endif -#if defined(Q_OS_VXWORKS) || defined (Q_OS_NACL) +#if (defined(Q_OS_VXWORKS) && !defined(VXWORKS_RTP)) || defined (Q_OS_NACL) #define QT_NO_DYNAMIC_LIBRARY #endif diff --git a/src/corelib/plugin/qlibrary_win.cpp b/src/corelib/plugin/qlibrary_win.cpp index f066ff2df4..16445f1163 100644 --- a/src/corelib/plugin/qlibrary_win.cpp +++ b/src/corelib/plugin/qlibrary_win.cpp @@ -46,10 +46,7 @@ #include "qfileinfo.h" #include <private/qfilesystementry_p.h> -#if defined(QT_NO_LIBRARY) && defined(Q_OS_WIN) -#undef QT_NO_LIBRARY -#pragma message("QT_NO_LIBRARY is not supported on Windows") -#endif +#ifndef QT_NO_LIBRARY #include <qt_windows.h> @@ -166,3 +163,5 @@ QFunctionPointer QLibraryPrivate::resolve_sys(const char* symbol) return QFunctionPointer(address); } QT_END_NAMESPACE + +#endif // QT_NO_LIBRARY diff --git a/src/corelib/plugin/qplugin.h b/src/corelib/plugin/qplugin.h index b6a533b793..b91a0e9900 100644 --- a/src/corelib/plugin/qplugin.h +++ b/src/corelib/plugin/qplugin.h @@ -45,8 +45,6 @@ #include <QtCore/qobject.h> #include <QtCore/qpointer.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -139,6 +137,4 @@ void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin staticPlugin); QT_END_NAMESPACE -QT_END_HEADER - #endif // Q_PLUGIN_H diff --git a/src/corelib/plugin/qpluginloader.h b/src/corelib/plugin/qpluginloader.h index 7eb48d530c..8f8833e839 100644 --- a/src/corelib/plugin/qpluginloader.h +++ b/src/corelib/plugin/qpluginloader.h @@ -44,15 +44,8 @@ #include <QtCore/qlibrary.h> -#if defined(QT_NO_LIBRARY) && defined(Q_OS_WIN) -#undef QT_NO_LIBRARY -#pragma message("QT_NO_LIBRARY is not supported on Windows") -#endif - #ifndef QT_NO_LIBRARY -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE class QLibraryPrivate; @@ -93,8 +86,6 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif // QT_NO_LIBRARY #endif //QPLUGINLOADER_H diff --git a/src/corelib/plugin/quuid.cpp b/src/corelib/plugin/quuid.cpp index 4ccf449ae2..4de83c62ee 100644 --- a/src/corelib/plugin/quuid.cpp +++ b/src/corelib/plugin/quuid.cpp @@ -279,7 +279,7 @@ static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCrypto The field layouts for the DCE versions listed in the table above are specified in the \l{http://www.ietf.org/rfc/rfc4122.txt} {Network Working Group UUID Specification}. - + Most platforms provide a tool for generating new UUIDs, e.g. \c uuidgen and \c guidgen. You can also use createUuid(). UUIDs generated by createUuid() are of the random type. Their @@ -534,23 +534,23 @@ QUuid QUuid::fromRfc4122(const QByteArray &bytes) \header \li Field # \li Source - + \row \li 1 \li data1 - + \row \li 2 \li data2 - + \row \li 3 \li data3 - + \row \li 4 \li data4[0] .. data4[1] - + \row \li 5 \li data4[2] .. data4[7] diff --git a/src/corelib/plugin/quuid.h b/src/corelib/plugin/quuid.h index bfd6759344..8bda617a3c 100644 --- a/src/corelib/plugin/quuid.h +++ b/src/corelib/plugin/quuid.h @@ -44,8 +44,6 @@ #include <QtCore/qstring.h> -QT_BEGIN_HEADER - #if defined(Q_OS_WIN) #ifndef GUID_DEFINED #define GUID_DEFINED @@ -227,6 +225,4 @@ Q_CORE_EXPORT uint qHash(const QUuid &uuid, uint seed = 0) Q_DECL_NOTHROW; QT_END_NAMESPACE -QT_END_HEADER - #endif // QUUID_H |