diff options
author | Kevin Smith <git@kismith.co.uk> | 2018-01-09 11:48:37 (GMT) |
---|---|---|
committer | Kevin Smith <git@kismith.co.uk> | 2018-01-09 11:48:37 (GMT) |
commit | 8e7a05d1501b7c77bcf908517b57b60563a0f2ae (patch) | |
tree | ecd1579ad365081971ee4337eb8a2faece6b8038 | |
parent | f978788a2c8844a24d2481c4d70b1bb5a152d1fb (diff) | |
download | swift-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.cpp | 9 |
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(); |