diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp index c9fbec8..2ce2543 100644 --- a/src/corelib/codecs/qtextcodec.cpp +++ b/src/corelib/codecs/qtextcodec.cpp @@ -1473,6 +1473,26 @@ QString QTextCodec::toUnicode(const char *chars) const return convertToUnicode(chars, len, 0); } +void QTextCodec::destroyCodecsForMib(int mib) +{ + if (!all) + return; + +#ifndef QT_NO_THREAD + QMutexLocker locker(textCodecsMutex()); +#endif + + QList::iterator itr = all->begin(); + while (itr != all->end()) { + QTextCodec *tc = *itr; + if (tc->mibEnum() == mib) { + itr = all->erase(itr); + delete tc; + } else { + ++itr; + } + } +} /*! \class QTextEncoder diff --git a/src/corelib/codecs/qtextcodec.h b/src/corelib/codecs/qtextcodec.h index 4ba8b85..f4e59f1 100644 --- a/src/corelib/codecs/qtextcodec.h +++ b/src/corelib/codecs/qtextcodec.h @@ -59,6 +59,8 @@ class QIODevice; class QTextDecoder; class QTextEncoder; +class QLibraryPrivate; + class Q_CORE_EXPORT QTextCodec { Q_DISABLE_COPY(QTextCodec) @@ -147,8 +149,10 @@ public: private: friend class QTextCodecCleanup; + friend class QLibraryPrivate; static QTextCodec *cftr; static bool validCodecs(); + static void destroyCodecsForMib(int mib); }; Q_DECLARE_OPERATORS_FOR_FLAGS(QTextCodec::ConversionFlags) diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp index a26dcd8..4517a78 100644 --- a/src/corelib/plugin/qfactoryloader.cpp +++ b/src/corelib/plugin/qfactoryloader.cpp @@ -67,7 +67,7 @@ public: ~QFactoryLoaderPrivate(); mutable QMutex mutex; QByteArray iid; - QList libraryList; + mutable QList > libraryList; QMap keyMap; QStringList keyList; QString suffix; @@ -79,8 +79,12 @@ public: QFactoryLoaderPrivate::~QFactoryLoaderPrivate() { - for (int i = 0; i < libraryList.count(); ++i) - libraryList.at(i)->release(); + for (int i = 0; i < libraryList.count(); ++i) { + if (libraryList.at(i).second) + libraryList.at(i).first->unload(); + + libraryList.at(i).first->release(); + } } QFactoryLoader::QFactoryLoader(const char *iid, @@ -135,6 +139,7 @@ void QFactoryLoader::update() library->release(); continue; } + bool did_load = false; QString regkey = QString::fromLatin1("Qt Factory Cache %1.%2/%3:/%4") .arg((QT_VERSION & 0xff0000) >> 16) .arg((QT_VERSION & 0xff00) >> 8) @@ -154,6 +159,7 @@ void QFactoryLoader::update() library->release(); continue; } + did_load = true; QObject *instance = library->instance(); if (!instance) // ignore plugins that have a valid signature but cannot be loaded. @@ -176,7 +182,7 @@ void QFactoryLoader::update() library->release(); continue; } - d->libraryList += library; + d->libraryList += QPair(library, did_load); for (int k = 0; k < keys.count(); ++k) { // first come first serve, unless the first // library was built with a future Qt version, @@ -233,13 +239,24 @@ QObject *QFactoryLoader::instance(const QString &key) const QString lowered = d->cs ? key : key.toLower(); if (QLibraryPrivate* library = d->keyMap.value(lowered)) { - if (library->instance || library->loadPlugin()) { - if (QObject *obj = library->instance()) { - if (obj && !obj->parent()) - obj->moveToThread(QCoreApplicationPrivate::mainThread()); - return obj; + if (!library->instance) { + if (!library->loadPlugin()) + return 0; + + QList >::iterator itr; + for (itr = d->libraryList.begin(); itr != d->libraryList.end(); ++itr) { + if (library == (*itr).first) { + (*itr).second = true; // mark this plugin as loaded + break; + } } } + + if (QObject *obj = library->instance()) { + if (obj && !obj->parent()) + obj->moveToThread(QCoreApplicationPrivate::mainThread()); + return obj; + } } return 0; } diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp index 1874a9e..de6cd5c 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -61,6 +61,8 @@ #include #include #include +#include +#include QT_BEGIN_NAMESPACE @@ -451,8 +453,21 @@ bool QLibraryPrivate::unload() if (!pHnd) return false; if (!libraryUnloadCount.deref()) { // only unload if ALL QLibrary instance wanted to - if (instance) - delete instance(); + if (instance) { + QObject *obj = instance(); + if (QTextCodecPlugin *tcPlugin = qobject_cast(obj)) { + // delete all text codecs created from this text codec plugin + QList listMibs = tcPlugin->mibEnums(); + QList::const_iterator itr = listMibs.constBegin(); + while (itr != listMibs.constEnd()) { + QTextCodec::destroyCodecsForMib(*itr); + ++itr; + } + } + + delete obj; + } + if (unload_sys()) { instance = 0; pHnd = 0;