Fix crash on account deletion

Calling forgetSensitiveData() on account deletion leads to a timer for
clearQNAMCache() being queued. Then the Account object is deleted. The
Credentials object stays alive for now because it has a deleteLater
deleter.

If the timer calls into a slot on the Credentials object, the _account
pointer will be invalid at this time.

As a workaround, move the target slot to Account - that way it will not
be called as the account object is already destroyed.

However since Account and Credentials are mutually dependent, it would
be much preferable if their lifetimes were linked, avoiding this
category of bugs.

The current behavior was introduced in
d40c56eda5 and I currently don't
understand why - maybe there's another way of dealing with the problem
that existed then.
This commit is contained in:
Christian Kamm 2017-07-06 13:43:34 +02:00 committed by ckamm
parent ce8341ca1f
commit d01065b9a1
4 changed files with 10 additions and 11 deletions

View file

@ -391,6 +391,11 @@ void Account::handleInvalidCredentials()
emit invalidCredentials(); emit invalidCredentials();
} }
void Account::clearQNAMCache()
{
_am->clearAccessCache();
}
const Capabilities &Account::capabilities() const const Capabilities &Account::capabilities() const
{ {
return _capabilities; return _capabilities;

View file

@ -197,6 +197,10 @@ public:
/// Called by network jobs on credential errors, emits invalidCredentials() /// Called by network jobs on credential errors, emits invalidCredentials()
void handleInvalidCredentials(); void handleInvalidCredentials();
public slots:
/// Used when forgetting credentials
void clearQNAMCache();
signals: signals:
/// Emitted whenever there's network activity /// Emitted whenever there's network activity
void propagatorNetworkActivity(); void propagatorNetworkActivity();

View file

@ -370,16 +370,7 @@ void HttpCredentials::invalidateToken()
// indirectly) from QNetworkAccessManagerPrivate::authenticationRequired, which itself // indirectly) from QNetworkAccessManagerPrivate::authenticationRequired, which itself
// is a called from a BlockingQueuedConnection from the Qt HTTP thread. And clearing the // is a called from a BlockingQueuedConnection from the Qt HTTP thread. And clearing the
// cache needs to synchronize again with the HTTP thread. // cache needs to synchronize again with the HTTP thread.
QTimer::singleShot(0, this, SLOT(clearQNAMCache())); QTimer::singleShot(0, _account, SLOT(clearQNAMCache()));
}
void HttpCredentials::clearQNAMCache()
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
_account->networkAccessManager()->clearAccessCache();
#else
_account->resetNetworkAccessManager();
#endif
} }
void HttpCredentials::forgetSensitiveData() void HttpCredentials::forgetSensitiveData()

View file

@ -110,7 +110,6 @@ private Q_SLOTS:
void slotWriteClientCertPEMJobDone(QKeychain::Job *); void slotWriteClientCertPEMJobDone(QKeychain::Job *);
void slotWriteClientKeyPEMJobDone(QKeychain::Job *); void slotWriteClientKeyPEMJobDone(QKeychain::Job *);
void slotWriteJobDone(QKeychain::Job *); void slotWriteJobDone(QKeychain::Job *);
void clearQNAMCache();
protected: protected:
QString _user; QString _user;