Commit 20a249c5 authored by flypig's avatar flypig

[qtbase] Ignore Connecting states received after session has closed. Contributes to JB#46185

QNetworkManager keeps track of a single connected session (e.g. Wifi,
mobile data) at a time. If the currently tracked session disconnects, it
relies on receiving a status update from the session in order to trigger
it to move to a different connection.

As part of this, it also relies on the signals it connects to from the
QNetworkSession being queued, because QueuedConnection sends its
closed() signal before it sends its Disconnected stateChanged() signal.
QNetworkManager disconnects the signals on receiving the closed()
signal, but still needs to receive the Disconnected stateChanged()
signal in order to trigger a switch to a different connection.

Unfortunately, QNetworkSession can also send out Connecting
stateChanged() signals after the closed() signal, and these are handled
badly by QNetworkSession. The problemmatic sequence is:

1. QNetworkManager receives a closed() signal and disconnects from the
QNetworkSession.
2. QNetworkManager receives a Connecting stateChanged() signal and sets
itself to offline, but doesn't switch to another connection.
3. QNetworkManager never receives any other signals from the now
disconnected QNetworkSession, and so never changes state again and
remains offline indefinitely.

The only way to get out stage 3 is to go completely offline (e.g. turn
off both Wifi and mobile data), because QNetworkManager also listens
separately for offline/online signals. In contrast, disconnecting and
reconnecting Wifi connections, or mobile data, without ever going fully
offline, never gets out of state 3.

This change forces QNetworkManager to ignore Connecting stateChanged()
signals if they occur when there is no active QNetworkSession, so that
stage 2 never happens.
parent eef21594
......@@ -1652,6 +1652,12 @@ void QNetworkAccessManagerPrivate::_q_networkSessionClosed()
void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession::State state)
{
Q_Q(QNetworkAccessManager);
if ((state == QNetworkSession::Connecting) && (!getNetworkSession())) {
qCWarning(lcNetworkAccess) << "QNAM: ignoring Connecting state received after the session closed";
return;
}
bool reallyOnline = false;
//Do not emit the networkSessionConnected signal here, except for roaming -> connected
//transition, otherwise it is emitted twice in a row when opening a connection.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment