From 3b8075de3b3c842311c157476a85d2cf9ddff403 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 25 Oct 2018 16:32:13 -0700 Subject: Fix deleting of QSharedPointer internals in case QPointer loses the race MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QPointer uses QWeakPointer / QSharedPointer internals in QObject and has the code to make sure two threads won't stomp on each other if both try to create a QPointer for the same QObject at the same time. The threading code was fine, but had a mistake in the clean up code for the loser thread: the QtSharedPointer::ExternalRefCountData destructor has a Q_ASSERT for the state of the reference counts. So we need to set the state correctly before calling the destructor. But we don't want to do it in case the Q_ASSERT compiled to nothing. So we use a hack that violates the Second Rule of Q_ASSERTs: don't do something with side-effects. This way, we can insert code that will only be compiled if Q_ASSERTs do something, without having to duplicate the preprocessor conditions from qglobal.h. Fixes: QTBUG-71412 Change-Id: I1bd327aeaf73421a8ec5fffd1560fdfc8b73b70c Reviewed-by: Romain Pokrzywka Reviewed-by: Jędrzej Nowacki --- src/corelib/tools/qsharedpointer.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/corelib/tools/qsharedpointer.cpp') diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp index 2d5fd2a00e..65616e2abb 100644 --- a/src/corelib/tools/qsharedpointer.cpp +++ b/src/corelib/tools/qsharedpointer.cpp @@ -1466,6 +1466,9 @@ QtSharedPointer::ExternalRefCountData *QtSharedPointer::ExternalRefCountData::ge x->strongref.store(-1); x->weakref.store(2); // the QWeakPointer that called us plus the QObject itself if (!d->sharedRefcount.testAndSetRelease(0, x)) { + // ~ExternalRefCountData has a Q_ASSERT, so we use this trick to + // only execute this if Q_ASSERTs are enabled + Q_ASSERT((x->weakref.store(0), true)); delete x; x = d->sharedRefcount.loadAcquire(); x->weakref.ref(); -- cgit v1.2.3