From 782df5b41dd3ab098fd1d3233339079487e1812f Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Fri, 11 Oct 2019 00:42:08 +0200 Subject: Make QObjectPrivate::threadData a proper atomic QObjectPrivate::threadData used to be a QThreadData *, and was read and written from multiple threads without proper synchronization. As an example, it was read from QCoreApplication::postEvent and written from QObject::moveToThread, therefore causing UB. Port threadData to a proper atomic, removing the races. Fix all usage points. In general, QObject is documented to be simply reentrant, not thread-safe, and certain bits (e.g. timers, moveToThread) are not even reentrant. The reasoning therefore is that a given QObject's threadData is not supposed to be touched by multiple threads without some synchronization happening elsewhere, and therefore relaxed loads should be sufficient. As drive-by change: refactor QCoreApplication::postEvent. It was particularly subtle, because it had a loop using a volatile to cope with the possibility of the receiver object switching thread while we tried to lock its thread's event queue. However, volatile does not achieve any synchronization, so drop it, and refactor the algorithm using better locking primitives. Put this algorithm in a common place, and also reuse it from removePostedEvents, which was lacking any synchronization. Change-Id: Icc755f7eb418ff54b33db4bdd87fd8eaf4e82c7a Reviewed-by: Thiago Macieira --- src/widgets/kernel/qapplication.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/widgets/kernel') diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index dfa1bc23b1..6d4baacfef 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -3660,7 +3660,7 @@ bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e) // send to all application event filters if (threadRequiresCoreApplication() - && receiver->d_func()->threadData->thread.loadAcquire() == mainThread() + && receiver->d_func()->threadData.loadRelaxed()->thread.loadAcquire() == mainThread() && sendThroughApplicationEventFilters(receiver, e)) { filtered = true; return filtered; -- cgit v1.2.3