Fix crash on account deletion
authorChristian Kamm <mail@ckamm.de>
Thu, 6 Jul 2017 11:43:34 +0000 (13:43 +0200)
committerckamm <mail@ckamm.de>
Thu, 6 Jul 2017 12:34:02 +0000 (14:34 +0200)
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
d40c56eda561e3a541bf1b23f70fa8d659d3037e and I currently don't
understand why - maybe there's another way of dealing with the problem
that existed then.

src/libsync/account.cpp
src/libsync/account.h
src/libsync/creds/httpcredentials.cpp
src/libsync/creds/httpcredentials.h

index 39d15f9719b2660414fc7ace3031e8aa820ab1ac..19ace5ed0a6ce3050793cd2bfdda26222371d2a2 100644 (file)
@@ -391,6 +391,11 @@ void Account::handleInvalidCredentials()
     emit invalidCredentials();
 }
 
+void Account::clearQNAMCache()
+{
+    _am->clearAccessCache();
+}
+
 const Capabilities &Account::capabilities() const
 {
     return _capabilities;
index 4e554e59083c2906e7a318035d49688e3e50b7dd..66e0d1be6114546643c3bdcbcae643c477cfbf3c 100644 (file)
@@ -197,6 +197,10 @@ public:
     /// Called by network jobs on credential errors, emits invalidCredentials()
     void handleInvalidCredentials();
 
+public slots:
+    /// Used when forgetting credentials
+    void clearQNAMCache();
+
 signals:
     /// Emitted whenever there's network activity
     void propagatorNetworkActivity();
index ce37ce93ee4677073c920fbbda830300fe44071a..1670e0101e4a576cc6678cf66b8e9026b55e3c85 100644 (file)
@@ -370,16 +370,7 @@ void HttpCredentials::invalidateToken()
     // indirectly) from QNetworkAccessManagerPrivate::authenticationRequired, which itself
     // is a called from a BlockingQueuedConnection from the Qt HTTP thread. And clearing the
     // cache needs to synchronize again with the HTTP thread.
-    QTimer::singleShot(0, this, SLOT(clearQNAMCache()));
-}
-
-void HttpCredentials::clearQNAMCache()
-{
-#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
-    _account->networkAccessManager()->clearAccessCache();
-#else
-    _account->resetNetworkAccessManager();
-#endif
+    QTimer::singleShot(0, _account, SLOT(clearQNAMCache()));
 }
 
 void HttpCredentials::forgetSensitiveData()
index 45b01c5ee5c4f48e35d762346ce954b355f6f71e..03f3b8c702b0a496fbb8d8cdc1d641ffbdc2093c 100644 (file)
@@ -110,7 +110,6 @@ private Q_SLOTS:
     void slotWriteClientCertPEMJobDone(QKeychain::Job *);
     void slotWriteClientKeyPEMJobDone(QKeychain::Job *);
     void slotWriteJobDone(QKeychain::Job *);
-    void clearQNAMCache();
 
 protected:
     QString _user;