summaryrefslogtreecommitdiffstats
path: root/src/corelib/plugin
diff options
context:
space:
mode:
authorSergio Ahumada <sergio.ahumada@digia.com>2013-03-20 23:30:31 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-03-20 23:30:31 +0100
commite5a11fbb3251a98fafd6bebf0b6fc366acb19088 (patch)
tree8e1bd6704205307e0a23484221ea1bb67a9f411e /src/corelib/plugin
parent0646d1131b4bc65cdd9af29f4ce00fdd2398a3df (diff)
parent76c0be34cd4ff4564693162fa7528463e23ce9d8 (diff)
Merge "Merge branch 'dev' into stable" into refs/staging/stable
Diffstat (limited to 'src/corelib/plugin')
-rw-r--r--src/corelib/plugin/qfactoryinterface.h4
-rw-r--r--src/corelib/plugin/qlibrary.cpp173
-rw-r--r--src/corelib/plugin/qlibrary.h10
-rw-r--r--src/corelib/plugin/qlibrary_p.h9
-rw-r--r--src/corelib/plugin/qlibrary_unix.cpp2
-rw-r--r--src/corelib/plugin/qlibrary_win.cpp7
-rw-r--r--src/corelib/plugin/qplugin.h4
-rw-r--r--src/corelib/plugin/qpluginloader.h9
-rw-r--r--src/corelib/plugin/quuid.cpp12
-rw-r--r--src/corelib/plugin/quuid.h4
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