diff options
author | Raphael Kubo da Costa <rakuco@FreeBSD.org> | 2016-08-22 19:55:10 +0200 |
---|---|---|
committer | Raphael Kubo da Costa <rakuco@FreeBSD.org> | 2016-08-23 15:37:00 +0000 |
commit | 680ec54a76eaf63375f648819ac9f98c915e5c43 (patch) | |
tree | 8a58aaee4087f9ae687d9bdbf9705133e69d0933 /src | |
parent | 5e3f770ad5e47f296b4782c0b6c5b03162027500 (diff) | |
download | qtbase-680ec54a76eaf63375f648819ac9f98c915e5c43.tar.gz |
QMutex: Make freelist() return a real global static
Since Qt 5.6.0, some applications such as Kate (built with clang, libc++
and libcxxrt) on FreeBSD occasionally crash with the following error
message on exit:
QMutex::lock(): sem_wait failure: Invalid argument
[or pthread_cond_wait in the 5.6 branch]
Investigation by Gleb Popov, Thiago Macieira and Olivier Goffart has
shown that this is caused by the fact that QDBusConnectionManager is a
Q_GLOBAL_STATIC (so it will be destroyed with all the other
Q_GLOBAL_STATICs in the reverse order of construction). In the
Q_COMPILER_THREADSAFE_STATICS case, freelist() also returns a
function-level static that is constructed on first use, so it may be
destroyed earlier than the QDBusConnectionManager object, making it
impossible to lock a contended mutex.
We now make freelist() return a global static, so that it is always
destroyed after QDBusConnectionManager and other function-static
variables.
Change-Id: I210fa7c18dbdf2345863da49141b9a85cffdef52
Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/thread/qmutex.cpp | 27 |
1 files changed, 2 insertions, 25 deletions
diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp index fa3bb080ae..e9709e34c5 100644 --- a/src/corelib/thread/qmutex.cpp +++ b/src/corelib/thread/qmutex.cpp @@ -571,34 +571,11 @@ const int FreeListConstants::Sizes[FreeListConstants::BlockCount] = { typedef QFreeList<QMutexPrivate, FreeListConstants> FreeList; // We cannot use Q_GLOBAL_STATIC because it uses QMutex -#if defined(Q_COMPILER_THREADSAFE_STATICS) +static FreeList freeList_; FreeList *freelist() { - static FreeList list; - return &list; + return &freeList_; } -#else -static QBasicAtomicPointer<FreeList> freeListPtr; - -FreeList *freelist() -{ - FreeList *local = freeListPtr.loadAcquire(); - if (!local) { - local = new FreeList; - if (!freeListPtr.testAndSetRelease(0, local)) { - delete local; - local = freeListPtr.loadAcquire(); - } - } - return local; -} - -static void qFreeListDeleter() -{ - delete freeListPtr.load(); -} -Q_DESTRUCTOR_FUNCTION(qFreeListDeleter) -#endif } QMutexPrivate *QMutexPrivate::allocate() |