summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Smith <git@kismith.co.uk>2018-01-09 11:48:37 (GMT)
committerKevin Smith <git@kismith.co.uk>2018-01-09 11:48:37 (GMT)
commit8e7a05d1501b7c77bcf908517b57b60563a0f2ae (patch)
treeecd1579ad365081971ee4337eb8a2faece6b8038
parentf978788a2c8844a24d2481c4d70b1bb5a152d1fb (diff)
downloadswift-8e7a05d1501b7c77bcf908517b57b60563a0f2ae.zip
swift-8e7a05d1501b7c77bcf908517b57b60563a0f2ae.tar.bz2
Avoid crash with Connector failure race condition
We were seeing crashes on macOS on a slept laptop overnight, very rarely. The backtraces pointed to accessing a deleted currentConnection in Connector. Eyeballing the code for a path that could trigger this, if the timer fires onTick, queing on the eventloop, and before that event is processed the connection queues onConnectFinished in the event loop, currentConnection will be reset by the timeout tick handling, and will then boom when the handleConnectionConnectFinished is called for onConnectFinished. Test-Information: Eyeballs Change-Id: Iaf4af1450ca8ee13761a33c0dc75f0311d2291b2
-rw-r--r--Swiften/Network/Connector.cpp9
1 files changed, 8 insertions, 1 deletions
diff --git a/Swiften/Network/Connector.cpp b/Swiften/Network/Connector.cpp
index e86b327..5eddaba 100644
--- a/Swiften/Network/Connector.cpp
+++ b/Swiften/Network/Connector.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2016 Isode Limited.
+ * Copyright (c) 2010-2018 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -148,6 +148,13 @@ void Connector::handleConnectionConnectFinished(bool error) {
timer->stop();
timer.reset();
}
+ if (!currentConnection) {
+ // We've hit a race condition where multiple finisheds were on the eventloop queue at once.
+ // This is particularly likely on macOS where the hourly momentary wakeup while asleep
+ // can cause both a timeout and an onConnectFinished to be queued sequentially (SWIFT-232).
+ // Let the first one process as normal, but ignore the second.
+ return;
+ }
currentConnection->onConnectFinished.disconnect(boost::bind(&Connector::handleConnectionConnectFinished, shared_from_this(), _1));
if (error) {
currentConnection.reset();