Don't allow the QLibraryStore to be recreated during shutdown
When QtCore's global destructors are run, they delete the global QLibraryStore qt_library_data and set the pointer to null. If something happened to call QLibraryStore::instance() later, it would be recreated and then weird things might happen. So prevent that from happening. That usually cannot happen, since the only thing that can run after QtCore global destructors are other QtCore global destructors or global destructors from libraries that do not depend on QtCore. So we're reasonably safe. There are two conditions in which something could run after QLibraryStore::cleanup() and still try to access QLibraryStore: 1) indirect dependency, like a global destructor from a library that doesn't depend on QtCore running code from another module that does. 2) static builds of Qt modules. In that case, the order of the global destructors is totally arbitrary and we could get one from a module that depends on QtCore running after QtCore's. That is the case from the bug report. Task-number: QTBUG-36294 Change-Id: Id199671275fd2535acf2d158857ce46b474e579b Reviewed-by: Kai Koehne <kai.koehne@digia.com> Reviewed-by: Tim Jenssen <tim.jenssen@digia.com>
This commit is contained in:
parent
2a2936b335
commit
5aee85ec23
@ -374,6 +374,7 @@ private:
|
||||
|
||||
static QBasicMutex qt_library_mutex;
|
||||
static QLibraryStore *qt_library_data = 0;
|
||||
static bool qt_library_data_once;
|
||||
|
||||
QLibraryStore::~QLibraryStore()
|
||||
{
|
||||
@ -429,8 +430,11 @@ Q_DESTRUCTOR_FUNCTION(qlibraryCleanup)
|
||||
// must be called with a locked mutex
|
||||
QLibraryStore *QLibraryStore::instance()
|
||||
{
|
||||
if (Q_UNLIKELY(!qt_library_data))
|
||||
if (Q_UNLIKELY(!qt_library_data_once && !qt_library_data)) {
|
||||
// only create once per process lifetime
|
||||
qt_library_data = new QLibraryStore;
|
||||
qt_library_data_once = true;
|
||||
}
|
||||
return qt_library_data;
|
||||
}
|
||||
|
||||
@ -440,11 +444,14 @@ inline QLibraryPrivate *QLibraryStore::findOrCreate(const QString &fileName, con
|
||||
QLibraryStore *data = instance();
|
||||
|
||||
// check if this library is already loaded
|
||||
QLibraryPrivate *lib = data->libraryMap.value(fileName);
|
||||
QLibraryPrivate *lib = 0;
|
||||
if (Q_LIKELY(data))
|
||||
lib = data->libraryMap.value(fileName);
|
||||
if (!lib)
|
||||
lib = new QLibraryPrivate(fileName, version);
|
||||
|
||||
// track this library
|
||||
if (Q_LIKELY(data))
|
||||
data->libraryMap.insert(fileName, lib);
|
||||
|
||||
lib->libraryRefCount.ref();
|
||||
@ -464,9 +471,11 @@ inline void QLibraryStore::releaseLibrary(QLibraryPrivate *lib)
|
||||
// no one else is using
|
||||
Q_ASSERT(lib->libraryUnloadCount.load() == 0);
|
||||
|
||||
if (Q_LIKELY(data)) {
|
||||
QLibraryPrivate *that = data->libraryMap.take(lib->fileName);
|
||||
Q_ASSERT(lib == that);
|
||||
Q_UNUSED(that);
|
||||
}
|
||||
delete lib;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user