From 1b29ef627ce8e69dbe2daae73bc6a9f57b631b3d Mon Sep 17 00:00:00 2001 From: Lorn Potter Date: Wed, 29 Jul 2015 13:33:51 +1000 Subject: [PATCH] Fix hang in qnam when disconnecting Generate error for network requests when connection gets disconnected. Documentation states that QNAM requests will fail if network is not accessible, so we need to track session state. Task-number: QTBUG-47482 Change-Id: I2c2d348637f72b2a908b438a66aa543a878de1e5 Reviewed-by: Timo Jyrinki Reviewed-by: Richard J. Moore --- src/network/access/qnetworkreplyhttpimpl.cpp | 15 +++++++++++++++ src/network/access/qnetworkreplyhttpimpl_p.h | 2 ++ src/network/access/qnetworkreplyimpl.cpp | 15 +++++++++++++++ src/network/access/qnetworkreplyimpl_p.h | 2 ++ 4 files changed, 34 insertions(+) diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index abc6603be26..c1956ae99fa 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -1676,6 +1676,11 @@ void QNetworkReplyHttpImplPrivate::_q_startOperation() Q_ARG(QString, QCoreApplication::translate("QNetworkReply", "backend start error."))); QMetaObject::invokeMethod(q, "_q_finished", synchronous ? Qt::DirectConnection : Qt::QueuedConnection); return; +#endif + } else { +#ifndef QT_NO_BEARERMANAGEMENT + QObject::connect(session.data(), SIGNAL(stateChanged(QNetworkSession::State)), + q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection); #endif } @@ -1844,6 +1849,16 @@ void QNetworkReplyHttpImplPrivate::_q_networkSessionConnected() } } +void QNetworkReplyHttpImplPrivate::_q_networkSessionStateChanged(QNetworkSession::State sessionState) +{ + if (sessionState == QNetworkSession::Disconnected + && (state != Idle || state != Reconnecting)) { + error(QNetworkReplyImpl::NetworkSessionFailedError, + QCoreApplication::translate("QNetworkReply", "Network session error.")); + finished(); + } +} + void QNetworkReplyHttpImplPrivate::_q_networkSessionFailed() { // Abort waiting and working replies. diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h index b009092196e..cfc05edbd80 100644 --- a/src/network/access/qnetworkreplyhttpimpl_p.h +++ b/src/network/access/qnetworkreplyhttpimpl_p.h @@ -95,6 +95,7 @@ public: #ifndef QT_NO_BEARERMANAGEMENT Q_PRIVATE_SLOT(d_func(), void _q_networkSessionConnected()) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed()) + Q_PRIVATE_SLOT(d_func(), void _q_networkSessionStateChanged(QNetworkSession::State)) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies)) #endif Q_PRIVATE_SLOT(d_func(), void _q_finished()) @@ -170,6 +171,7 @@ public: #ifndef QT_NO_BEARERMANAGEMENT void _q_networkSessionConnected(); void _q_networkSessionFailed(); + void _q_networkSessionStateChanged(QNetworkSession::State); void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies); #endif void _q_finished(); diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index f235adaee85..18f322f45dd 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -126,6 +126,11 @@ void QNetworkReplyImplPrivate::_q_startOperation() finished(); #endif return; + } else { +#ifndef QT_NO_BEARERMANAGEMENT + QObject::connect(session.data(), SIGNAL(stateChanged(QNetworkSession::State)), + q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection); +#endif } #ifndef QT_NO_BEARERMANAGEMENT @@ -310,6 +315,16 @@ void QNetworkReplyImplPrivate::_q_networkSessionConnected() } } +void QNetworkReplyImplPrivate::_q_networkSessionStateChanged(QNetworkSession::State sessionState) +{ + if (sessionState == QNetworkSession::Disconnected + && (state != Idle || state != Reconnecting)) { + error(QNetworkReplyImpl::NetworkSessionFailedError, + QCoreApplication::translate("QNetworkReply", "Network session error.")); + finished(); + } +} + void QNetworkReplyImplPrivate::_q_networkSessionFailed() { // Abort waiting and working replies. diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h index d2e7d02408e..5883c9d1c37 100644 --- a/src/network/access/qnetworkreplyimpl_p.h +++ b/src/network/access/qnetworkreplyimpl_p.h @@ -89,6 +89,7 @@ public: #ifndef QT_NO_BEARERMANAGEMENT Q_PRIVATE_SLOT(d_func(), void _q_networkSessionConnected()) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed()) + Q_PRIVATE_SLOT(d_func(), void _q_networkSessionStateChanged(QNetworkSession::State)) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies)) #endif @@ -124,6 +125,7 @@ public: #ifndef QT_NO_BEARERMANAGEMENT void _q_networkSessionConnected(); void _q_networkSessionFailed(); + void _q_networkSessionStateChanged(QNetworkSession::State); void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies); #endif