summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread/qmutex.cpp
diff options
context:
space:
mode:
authorRaphael Kubo da Costa <rakuco@FreeBSD.org>2016-08-22 19:55:10 +0200
committerRaphael Kubo da Costa <rakuco@FreeBSD.org>2016-08-23 15:37:00 +0000
commit680ec54a76eaf63375f648819ac9f98c915e5c43 (patch)
tree8a58aaee4087f9ae687d9bdbf9705133e69d0933 /src/corelib/thread/qmutex.cpp
parent5e3f770ad5e47f296b4782c0b6c5b03162027500 (diff)
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/corelib/thread/qmutex.cpp')
-rw-r--r--src/corelib/thread/qmutex.cpp27
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()