Details
-
Bug
-
Resolution: Unresolved
-
P3: Somewhat important
-
None
-
6.7.2
-
None
-
Qt 6.7.2 build with Clang 19 with flags '-debug' and '-sanitize thread'
Description
TSAN reports a data race in the following code:
#include <QCoreApplication> #include <QNetworkAccessManager> #include <QNetworkReply> int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); QUrl url("https://jsonplaceholder.typicode.com/posts/1"); // Example URL QNetworkRequest request(url); QEventLoop loop; QNetworkAccessManager manager; QNetworkReply *reply = manager.get(request); QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); loop.exec(); return 0; }
Output:
================== WARNING: ThreadSanitizer: data race on vptr (ctor/dtor vs virtual call) (pid=21616) Write of size 8 at 0x72480000e580 by thread T1: #0 QObject::~QObject() /qt5/qtbase/src/corelib/kernel/qobject.cpp:1041:1 (libQt6Core.so.6+0x33df20) #1 QHttpThreadDelegate::~QHttpThreadDelegate() /qt5/qtbase/src/network/access/qhttpthreaddelegate.cpp:181:1 (libQt6Network.so.6+0x261803) #2 QHttpThreadDelegate::~QHttpThreadDelegate() /qt5/qtbase/src/network/access/qhttpthreaddelegate.cpp:170:1 (libQt6Network.so.6+0x261839) #3 qDeleteInEventHandler(QObject*) /qt5/qtbase/src/corelib/kernel/qobject.cpp:5002:5 (libQt6Core.so.6+0x33fd2d) #4 QObject::event(QEvent*) /qt5/qtbase/src/corelib/kernel/qobject.cpp:1437:9 (libQt6Core.so.6+0x33f993) #5 QCoreApplicationPrivate::notify_helper(QObject*, QEvent*) /qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1316:26 (libQt6Core.so.6+0x25df96) #6 doNotify(QObject*, QEvent*) /qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1243:47 (libQt6Core.so.6+0x25d7e8) #7 QCoreApplication::notify(QObject*, QEvent*) /qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1226:12 (libQt6Core.so.6+0x25d981) #8 QCoreApplication::notifyInternal2(QObject*, QEvent*) /qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1142:18 (libQt6Core.so.6+0x25d69e) #9 QCoreApplication::sendEvent(QObject*, QEvent*) /qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1583:12 (libQt6Core.so.6+0x25e99e) #10 QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) /qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1940:9 (libQt6Core.so.6+0x25ffd8) #11 QEventDispatcherUNIX::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) /qt5/qtbase/src/corelib/kernel/qeventdispatcher_unix.cpp:415:5 (libQt6Core.so.6+0x6d0b36) #12 QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) /qt5/qtbase/src/corelib/kernel/qeventloop.cpp:100:55 (libQt6Core.so.6+0x281bc8) #13 QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) /qt5/qtbase/src/corelib/kernel/qeventloop.cpp:182:9 (libQt6Core.so.6+0x281e2b) #14 QThread::exec() /qt5/qtbase/src/corelib/thread/qthread.cpp:586:32 (libQt6Core.so.6+0x4fdbd2) #15 QThread::run() /qt5/qtbase/src/corelib/thread/qthread.cpp:707:12 (libQt6Core.so.6+0x4fe365) #16 QThreadPrivate::start(void*)::$_0::operator()() const /qt5/qtbase/src/corelib/thread/qthread_unix.cpp:326:14 (libQt6Core.so.6+0x6cd9b0) #17 void (anonymous namespace)::terminate_on_exception<QThreadPrivate::start(void*)::$_0>(QThreadPrivate::start(void*)::$_0&&) /qt5/qtbase/src/corelib/thread/qthread_unix.cpp:262:9 (libQt6Core.so.6+0x6cbe55) #18 QThreadPrivate::start(void*) /qt5/qtbase/src/corelib/thread/qthread_unix.cpp:285:5 (libQt6Core.so.6+0x6cbd59) Previous read of size 8 at 0x72480000e580 by main thread (mutexes: write M0): #0 QObject::~QObject() /qt5/qtbase/src/corelib/kernel/qobject.cpp:1117:73 (libQt6Core.so.6+0x33e4be) #1 QIODevice::~QIODevice() /qt5/qtbase/src/corelib/io/qiodevice.cpp:466:1 (libQt6Core.so.6+0x1cbe15) #2 QNetworkReply::~QNetworkReply() /qt5/qtbase/src/network/access/qnetworkreply.cpp:457:1 (libQt6Network.so.6+0xdd375) #3 QNetworkReplyHttpImpl::~QNetworkReplyHttpImpl() /qt5/qtbase/src/network/access/qnetworkreplyhttpimpl.cpp:228:1 (libQt6Network.so.6+0x26be94) #4 QNetworkReplyHttpImpl::~QNetworkReplyHttpImpl() /qt5/qtbase/src/network/access/qnetworkreplyhttpimpl.cpp:225:1 (libQt6Network.so.6+0x26bf19) #5 void qDeleteAll<QList<QNetworkReply*>::const_iterator>(QList<QNetworkReply*>::const_iterator, QList<QNetworkReply*>::const_iterator) /qt5/qtbase/src/corelib/tools/qalgorithms.h:27:9 (libQt6Network.so.6+0xba896) #6 void qDeleteAll<QList<QNetworkReply*>>(QList<QNetworkReply*> const&) /qt5/qtbase/src/corelib/tools/qalgorithms.h:35:5 (libQt6Network.so.6+0xaac93) #7 QNetworkAccessManager::~QNetworkAccessManager() /qt5/qtbase/src/network/access/qnetworkaccessmanager.cpp:436:5 (libQt6Network.so.6+0xa370d) #8 main /root/src/src/main.cpp:19:1 (Test+0x2242f2) Location is heap block of size 376 at 0x72480000e580 allocated by main thread: #0 operator new(unsigned long) <null> (Test+0x21caa6) #1 QNetworkReplyHttpImplPrivate::postRequest(QNetworkRequest const&) /qt5/qtbase/src/network/access/qnetworkreplyhttpimpl.cpp:808:37 (libQt6Network.so.6+0x270d81) #2 QNetworkReplyHttpImplPrivate::_q_startOperation() /qt5/qtbase/src/network/access/qnetworkreplyhttpimpl.cpp:1898:5 (libQt6Network.so.6+0x26bdcf) #3 QNetworkReplyHttpImpl::QNetworkReplyHttpImpl(QNetworkAccessManager*, QNetworkRequest const&, QNetworkAccessManager::Operation&, QIODevice*) /qt5/qtbase/src/network/access/qnetworkreplyhttpimpl.cpp:220:12 (libQt6Network.so.6+0x26bbec) #4 QNetworkAccessManager::createRequest(QNetworkAccessManager::Operation, QNetworkRequest const&, QIODevice*) /qt5/qtbase/src/network/access/qnetworkaccessmanager.cpp:1281:44 (libQt6Network.so.6+0xa601e) #5 QNetworkAccessManager::get(QNetworkRequest const&) /qt5/qtbase/src/network/access/qnetworkaccessmanager.cpp:780:34 (libQt6Network.so.6+0xa43bf) #6 main /root/src/src/main.cpp:14:36 (Test+0x22421c) Mutex M0 (0x7f5eed7aa6c8) created at: #0 __tsan_mutex_pre_lock <null> (Test+0x1ef077) #1 QtTsan::mutexPreLock(void*, unsigned int) /qt5/qtbase/src/corelib/thread/qtsan_impl.h:38:5 (libQt6Core.so.6+0x11dcf1) #2 QBasicMutex::lock() /qt5/qtbase/src/corelib/thread/qmutex.h:38:9 (libQt6Core.so.6+0x11dc7b) #3 QOrderedMutexLocker::relock() /qt5/qtbase/src/corelib/thread/qorderedmutexlocker_p.h:69:29 (libQt6Core.so.6+0x35b79f) #4 QOrderedMutexLocker::QOrderedMutexLocker(QBasicMutex*, QBasicMutex*) /qt5/qtbase/src/corelib/thread/qorderedmutexlocker_p.h:40:9 (libQt6Core.so.6+0x354041) #5 QObjectPrivate::connectImpl(QObject const*, int, QObject const*, void**, QtPrivate::QSlotObjectBase*, int, int const*, QMetaObject const*) /qt5/qtbase/src/corelib/kernel/qobject.cpp:5232:25 (libQt6Core.so.6+0x34c1d7) #6 QObject::connectImpl(QObject const*, void**, QObject const*, void**, QtPrivate::QSlotObjectBase*, Qt::ConnectionType, int const*, QMetaObject const*) /qt5/qtbase/src/corelib/kernel/qobject.cpp:5189:12 (libQt6Core.so.6+0x34bfec) #7 QMetaObject::Connection QObjectPrivate::connect<void (QNetworkReply::*)(), void (QNetworkReplyHttpImplPrivate::*)()>(QtPrivate::FunctionPointer<void (QNetworkReply::*)()>::Object const*, void (QNetworkReply::*)(), QtPrivate::FunctionPointer<void (QNetworkReplyHttpImplPrivate::*)()>::Object const*, void (QNetworkReplyHttpImplPrivate::*)(), Qt::ConnectionType) /qt5/qtbase/src/corelib/kernel/qobject_p.h:318:12 (libQt6Network.so.6+0x27ad97) #8 QNetworkReplyHttpImpl::QNetworkReplyHttpImpl(QNetworkAccessManager*, QNetworkRequest const&, QNetworkAccessManager::Operation&, QIODevice*) /qt5/qtbase/src/network/access/qnetworkreplyhttpimpl.cpp:161:5 (libQt6Network.so.6+0x26b827) #9 QNetworkAccessManager::createRequest(QNetworkAccessManager::Operation, QNetworkRequest const&, QIODevice*) /qt5/qtbase/src/network/access/qnetworkaccessmanager.cpp:1281:44 (libQt6Network.so.6+0xa601e) #10 QNetworkAccessManager::get(QNetworkRequest const&) /qt5/qtbase/src/network/access/qnetworkaccessmanager.cpp:780:34 (libQt6Network.so.6+0xa43bf) #11 main /root/src/src/main.cpp:14:36 (Test+0x22421c) Thread T1 'QNetworkAccessM' (tid=21618, running) created by main thread at: #0 pthread_create <null> (Test+0x198225) #1 QThread::start(QThread::Priority) /qt5/qtbase/src/corelib/thread/qthread_unix.cpp:723:16 (libQt6Core.so.6+0x6cc922) #2 QNetworkAccessManagerPrivate::createThread() /qt5/qtbase/src/network/access/qnetworkaccessmanager.cpp:1694:17 (libQt6Network.so.6+0xa7fdb) #3 QNetworkReplyHttpImplPrivate::postRequest(QNetworkRequest const&) /qt5/qtbase/src/network/access/qnetworkreplyhttpimpl.cpp:639:34 (libQt6Network.so.6+0x26fa06) #4 QNetworkReplyHttpImplPrivate::_q_startOperation() /qt5/qtbase/src/network/access/qnetworkreplyhttpimpl.cpp:1898:5 (libQt6Network.so.6+0x26bdcf) #5 QNetworkReplyHttpImpl::QNetworkReplyHttpImpl(QNetworkAccessManager*, QNetworkRequest const&, QNetworkAccessManager::Operation&, QIODevice*) /qt5/qtbase/src/network/access/qnetworkreplyhttpimpl.cpp:220:12 (libQt6Network.so.6+0x26bbec) #6 QNetworkAccessManager::createRequest(QNetworkAccessManager::Operation, QNetworkRequest const&, QIODevice*) /qt5/qtbase/src/network/access/qnetworkaccessmanager.cpp:1281:44 (libQt6Network.so.6+0xa601e) #7 QNetworkAccessManager::get(QNetworkRequest const&) /qt5/qtbase/src/network/access/qnetworkaccessmanager.cpp:780:34 (libQt6Network.so.6+0xa43bf) #8 main /root/src/src/main.cpp:14:36 (Test+0x22421c) SUMMARY: ThreadSanitizer: data race on vptr (ctor/dtor vs virtual call) /qt5/qtbase/src/corelib/kernel/qobject.cpp:1041:1 in QObject::~QObject() ================== ThreadSanitizer: reported 1 warnings
From what I can understand the following happens: `QHttpThreadDelegate` is destroying in T1 (Networkmanager's thread) and meantime the main thread is calling `qDeleteAll<QList<QNetworkReply*>>` which calls `QObject::metaObject` for the `QHttpThreadDelegate` object. So one thread is calling destructor of the object and another thread is calling a virtual function of it. Technically this is a data race on vtable (this is what TSAN reports).
Attachments
Issue Links
- resulted from
-
QTBUG-34131 QNetworkReply::deleteLater() causes random crashes related to QNonContiguousByteDevice::~QNonContiguousByteDevice
-
- Closed
-