Skip to content

Commit

Permalink
Merge branch 'jb33794' into 'mer-stable'
Browse files Browse the repository at this point in the history
Fix the problem with QNetworkAccessManager getting stuck in NotAccessible state

It appears that `QNetworkAccessManager` can keep receiving queued signals even after it has cleared its reference to `QNetworkSession` and disconnected the slots. That can mess up `networkAccessible` state. Particularly, `QNetworkAccessManager` can get stuck in `NotAccessible` state and refuse to submit new network requests until the next online state change signal pulls it out of this state.

There still may be a possibility that a signal from an old `QNetworkSession` could arrive when `QNetworkAccessManager` has already switched to another `QNetworkSession`, but this scenario is probably broken by design, since for whatever reason `QNetworkAccessManager` is only tracking one `QNetworkSession`. In any case, it's far less likely than the scenario which I was trying to fix.

See merge request !3
  • Loading branch information
lpotter committed Jan 4, 2016
2 parents 21699ff + f97a2cf commit be8e74a
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 6 deletions.
7 changes: 7 additions & 0 deletions src/network/access/qnetworkaccessmanager.cpp
Expand Up @@ -1566,6 +1566,13 @@ void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession
{
Q_Q(QNetworkAccessManager);

if (!networkSessionStrongRef) {
// The next stateChanged() may already be queued by the time we have
// received closed() signal and cleared the session reference.
lastSessionState = QNetworkSession::Invalid;
return;
}

//Do not emit the networkSessionConnected signal here, except for roaming -> connected
//transition, otherwise it is emitted twice in a row when opening a connection.
if (state == QNetworkSession::Connected && lastSessionState == QNetworkSession::Roaming)
Expand Down
23 changes: 20 additions & 3 deletions src/plugins/bearer/connman/qconnmanengine.cpp
Expand Up @@ -239,14 +239,15 @@ QNetworkSession::State QConnmanEngine::sessionStateForId(const QString &id)
if (!ptr || !ptr->isValid)
return QNetworkSession::Invalid;

QString service = id;
QConnmanServiceInterface *serv = connmanServiceInterfaces.value(service);
QConnmanServiceInterface *serv = connmanServiceInterfaces.value(id);
if (!serv)
return QNetworkSession::Invalid;

QString servState = serv->state();

if (serv->favorite() && (servState == QLatin1String("idle") || servState == QLatin1String("failure"))) {
if (servState == QLatin1String("idle") ||
servState == QLatin1String("failure") ||
servState == QLatin1String("disconnect")) {
return QNetworkSession::Disconnected;
}

Expand Down Expand Up @@ -375,6 +376,22 @@ void QConnmanEngine::configurationChange(QConnmanServiceInterface *serv)

ptr->mutex.unlock();

if (!changed) {
const QNetworkSession::State curSessionState = sessionStateForId(id);
const QNetworkSession::State prevSessionState =
connmanLastKnownSessionState.contains(id) ?
connmanLastKnownSessionState.value(id) :
QNetworkSession::Invalid;
if (curSessionState != prevSessionState) {
if (curSessionState == QNetworkSession::Invalid) {
connmanLastKnownSessionState.remove(id);
} else {
connmanLastKnownSessionState.insert(id, curSessionState);
}
changed = true;
}
}

if (changed) {
locker.unlock();
emit configurationChanged(ptr);
Expand Down
4 changes: 1 addition & 3 deletions src/plugins/bearer/connman/qconnmanengine.h
Expand Up @@ -117,23 +117,21 @@ private Q_SLOTS:

QList<QNetworkConfigurationPrivate *> foundConfigurations;

QString networkFromId(const QString &id);

QNetworkConfiguration::StateFlags getStateForService(const QString &service);
QNetworkConfiguration::BearerType typeToBearer(const QString &type);

void removeConfiguration(const QString &servicePath);
void addServiceConfiguration(const QString &servicePath);
QDateTime activeTime;


QMap<QString,QConnmanTechnologyInterface *> technologies; // techpath, tech interface
QMap<QString,QString> configInterfaces; // id, interface name
QList<QString> serviceNetworks; //servpath

QNetworkConfiguration::BearerType ofonoTechToBearerType(const QString &type);
bool isRoamingAllowed(const QString &context);
QMap <QString,QConnmanServiceInterface *> connmanServiceInterfaces;
QMap <QString,QNetworkSession::State> connmanLastKnownSessionState;

protected:
bool requiresPolling() const;
Expand Down

0 comments on commit be8e74a

Please sign in to comment.