From 8e7a05d1501b7c77bcf908517b57b60563a0f2ae Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Tue, 9 Jan 2018 11:48:37 +0000
Subject: 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

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();
-- 
cgit v0.10.2-6-g49f6