Details
-
Bug
-
Resolution: Fixed
-
Not Evaluated
-
6.10.0
-
None
-
-
253f34082 (dev), df454f51f (6.9), 46d9b07de (6.8), 6f39ff2c7 (tqtc/lts-6.5)
Description
WARNING: ThreadSanitizer: data race (pid=391944) Atomic write of size 4 at 0x72040062aba0 by thread T103: #0 std::__atomic_base<int>::fetch_add(int, std::memory_order) /usr/include/c++/14/bits/atomic_base.h:631 (libQt6Core_tsan.so.6+0xf1f24) #1 bool QAtomicOps<int>::ref<int>(std::atomic<int>&) qtbase/src/corelib/thread/qatomic_cxx11.h:259 (libQt6Core_tsan.so.6+0xf1f24) #2 QBasicAtomicInteger<int>::ref() qtbase/src/corelib/thread/qbasicatomic.h:47 (libQt6Core_tsan.so.6+0xef5f6) #3 QtSharedPointer::ExternalRefCountData::getAndRef(QObject const*) qtbase/src/corelib/tools/qsharedpointer.cpp:1536 (libQt6Core_tsan.so.6+0x5f5cf2) #4 QWeakPointer<QObject>::QWeakPointer<QObject, true>(QObject*, bool) inst-tsan/include/QtCore/qsharedpointer_impl.h:773 #5 QWeakPointer<QObject>& QWeakPointer<QObject>::assign<QObject>(QObject*) inst-tsan/include/QtCore/qsharedpointer_impl.h:768 Previous write of size 8 at 0x72040062aba0 by thread T164: #0 operator new(unsigned long) <null> (libtsan.so.2+0xa75e1) #1 QtSharedPointer::ExternalRefCountData::getAndRef(QObject const*) qtbase/src/corelib/tools/qsharedpointer.cpp:1541 (libQt6Core_tsan.so.6+0x5f5d13) #2 QWeakPointer<QObject>::QWeakPointer<QObject, true>(QObject*, bool) inst-tsan/include/QtCore/qsharedpointer_impl.h:773 #3 QWeakPointer<QObject>& QWeakPointer<QObject>::assign<QObject>(QObject*) inst-tsan/include/QtCore/qsharedpointer_impl.h:768
1528│ QtSharedPointer::ExternalRefCountData *QtSharedPointer::ExternalRefCountData::getAndRef(const QObject *obj) 1529│ { 1530│ Q_ASSERT(obj); 1531│ QObjectPrivate *d = QObjectPrivate::get(const_cast<QObject *>(obj)); 1532│ Q_ASSERT_X(!d->wasDeleted, "QWeakPointer", "Detected QWeakPointer creation in a QObject being deleted"); 1533│ 1534│ ExternalRefCountData *that = d->sharedRefcount.loadRelaxed(); 1535│ if (that) { 1536├───────> that->weakref.ref(); 1537│ return that; 1538│ } 1539│ 1540│ // we can create the refcount data because it doesn't exist 1541│ ExternalRefCountData *x = ::new ExternalRefCountData(Qt::Uninitialized); 1542│ x->strongref.storeRelaxed(-1); 1543│ x->weakref.storeRelaxed(2); // the QWeakPointer that called us plus the QObject itself 1544│ 1545│ ExternalRefCountData *ret; 1546│ if (d->sharedRefcount.testAndSetOrdered(nullptr, x, ret)) { // ought to be release+acquire; this is acq_rel+acquire 1547│ ret = x; 1548│ } else { 1549│ // ~ExternalRefCountData has a Q_ASSERT, so we use this trick to 1550│ // only execute this if Q_ASSERTs are enabled 1551│ Q_ASSERT((x->weakref.storeRelaxed(0), true)); 1552│ ::delete x; 1553│ ret->weakref.ref(); 1554│ } 1555│ return ret; 1556│ }
TSAN is saying the that->weakref.ref() on line 1536 races with the initial state of weakref in new on line 1541. I am very puzzled by that because it got "replaced" with the storeRelaxed(2) on line 1543. I (or TSAN) must be missing something....