Details
-
Bug
-
Resolution: Done
-
P2: Important
-
4.7.0
-
None
-
Windows XP SP3.
Intel dual core CPU.
-
0570a0f3936a2f7d7ec5afef9fcea8193ef3c15c (4.8), aee4cbf22a5942c7bd4b9545a8fcb7cf2930e0ee (5.0)
Description
Calling directly QNetworkProxyFactory::systemProxyForQuery() can deadlock with QNetworkAccessManager methods when multiple threads are used.
Thread 1: calling QNetworkProxyFactory::systemProxyForQuery()
Thread 2: calling QNetworkAccessManager::get()
With suitable timing, the two threads become deadlocked.
in QNetworkProxyFactory::systemProxyForQuery(), thread 1 gets QWindowsSystemProxy, and locks a mutex in it. Few steps further, thread 1 gets to QGlobalNetworkProxy::init(), which is protected by a mutex in QGlobalNetworkProxy.
Meanwhile in thread 2, the QNetworkAccessManager::get() proceeds to QGlobalNetworkProxy::proxyForQuery, which locks the mutex in QGlobalNetworkProxy. Few calls later, thread 2 ends up in QNetworkProxyFactory::systemProxyForQuery(). But the mutex there is already locked by thread1, which is now waiting on the QGlobalNetworkProxy mutex which was locked by thread 2.
Thread 1:
QtCore4.dll!QMutexPrivate::wait(int timeout=0xffffffff) Line 63 + 0x16 bytes C++
QtCore4.dll!QMutex::lock() Line 172 C++
QtCore4.dll!QMutexLocker::QMutexLocker(QMutex * m=0x01ba6b20) Line 103 C++
QtNetwork4.dll!QGlobalNetworkProxy::init() Line 260 C++
QtNetwork4.dll!QNetworkProxy::QNetworkProxy(QNetworkProxy::ProxyType type=HttpProxy, const QString & hostName="**.*.*.**", unsigned short port=0x1f90, const QString & user="", const QString & password="") Line 445 C++
QtNetwork4.dll!parseServerList(const QNetworkProxyQuery & query=
> QtNetwork4.dll!QNetworkProxyFactory::systemProxyForQuery(const QNetworkProxyQuery & query={...}
) Line 394 + 0x10 bytes C++
Thread 2:
> QtCore4.dll!QMutexPrivate::wait(int timeout=0xffffffff) Line 63 + 0x16 bytes C++
QtCore4.dll!QMutex::lock() Line 209 C++
QtCore4.dll!QMutexLocker::QMutexLocker(QMutex * m=0x05d5be20) Line 103 C++
QtNetwork4.dll!QNetworkProxyFactory::systemProxyForQuery(const QNetworkProxyQuery & query=
QtNetwork4.dll!QSystemConfigurationProxyFactory::queryProxy(const QNetworkProxyQuery & query={...}
) Line 68 + 0x13 bytes C++
QtNetwork4.dll!QGlobalNetworkProxy::proxyForQuery(const QNetworkProxyQuery & query=
QtNetwork4.dll!QNetworkProxyFactory::proxyForQuery(const QNetworkProxyQuery & query={...}
) Line 1303 + 0x16 bytes C++
QtNetwork4.dll!QNetworkAccessManagerPrivate::queryProxy(const QNetworkProxyQuery & query=
QtNetwork4.dll!QNetworkAccessManager::createRequest(QNetworkAccessManager::Operation op=0x05d5e5f8, const QNetworkRequest & req={...}
, QIODevice * outgoingData=0x00000000) Line 1027 + 0x37 bytes C++
QtNetwork4.dll!QNetworkAccessManager::get(const QNetworkRequest & request=
) Line 688 + 0x14 bytes C++
QtDeclarative4.dll!QDeclarativeImageRequestHandler::event(QEvent * event=0x05d5c000) Line 289 C++
Attachments
For Gerrit Dashboard: QTBUG-13088 | ||||||
---|---|---|---|---|---|---|
# | Subject | Branch | Project | Status | CR | V |
16590,1 | Remove unnecessary locking from QNetworkProxy constructor | master | qt/qtbase | Status: MERGED | +2 | 0 |
16754,1 | Remove unnecessary locking from QNetworkProxy constructor | 4.8 | qt/qt | Status: MERGED | +2 | 0 |