From 9806bce403a57fa1f75b7646c7e8160338a2675a Mon Sep 17 00:00:00 2001
From: SamGondelman <samuel_gondelman@alumni.brown.edu>
Date: Mon, 6 Aug 2018 11:21:32 -0700
Subject: [PATCH] weak pointers to nodeList

---
 domain-server/src/DomainGatekeeper.cpp      |  6 ++++--
 domain-server/src/DomainServer.cpp          | 22 ++++++++++++---------
 interface/src/Application.cpp               |  6 ++++--
 interface/src/avatar/AvatarManager.cpp      | 21 ++++++++++++--------
 interface/src/ui/PreferencesDialog.cpp      | 18 ++++++++++++++---
 libraries/ui/src/ui/OffscreenQmlSurface.cpp |  2 +-
 6 files changed, 50 insertions(+), 25 deletions(-)

diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp
index 39ec5463dc..2307b1be3b 100644
--- a/domain-server/src/DomainGatekeeper.cpp
+++ b/domain-server/src/DomainGatekeeper.cpp
@@ -264,7 +264,8 @@ void DomainGatekeeper::updateNodePermissions() {
     QList<SharedNodePointer> nodesToKill;
 
     auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
-    limitedNodeList->eachNode([this, &limitedNodeList, &nodesToKill](const SharedNodePointer& node){
+    QWeakPointer<LimitedNodeList> limitedNodeListWeak = limitedNodeList;
+    limitedNodeList->eachNode([this, limitedNodeListWeak, &nodesToKill](const SharedNodePointer& node){
         // the id and the username in NodePermissions will often be the same, but id is set before
         // authentication and verifiedUsername is only set once they user's key has been confirmed.
         QString verifiedUsername = node->getPermissions().getVerifiedUserName();
@@ -296,7 +297,8 @@ void DomainGatekeeper::updateNodePermissions() {
                 machineFingerprint = nodeData->getMachineFingerprint();
 
                 auto sendingAddress = nodeData->getSendingSockAddr().getAddress();
-                isLocalUser = (sendingAddress == limitedNodeList->getLocalSockAddr().getAddress() ||
+                auto nodeList = limitedNodeListWeak.lock();
+                isLocalUser = ((nodeList && sendingAddress == nodeList->getLocalSockAddr().getAddress()) ||
                                sendingAddress == QHostAddress::LocalHost);
             }
 
diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp
index 05555314f3..7bf8720c86 100644
--- a/domain-server/src/DomainServer.cpp
+++ b/domain-server/src/DomainServer.cpp
@@ -1198,6 +1198,7 @@ QUuid DomainServer::connectionSecretForNodes(const SharedNodePointer& nodeA, con
 void DomainServer::broadcastNewNode(const SharedNodePointer& addedNode) {
 
     auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
+    QWeakPointer<LimitedNodeList> limitedNodeListWeak = limitedNodeList;
 
     auto addNodePacket = NLPacket::create(PacketType::DomainServerAddedNode);
 
@@ -1217,16 +1218,19 @@ void DomainServer::broadcastNewNode(const SharedNodePointer& addedNode) {
                 return false;
             }
         },
-        [this, &addNodePacket, connectionSecretIndex, addedNode, &limitedNodeList](const SharedNodePointer& node) {
-            addNodePacket->seek(connectionSecretIndex);
-
-            QByteArray rfcConnectionSecret = connectionSecretForNodes(node, addedNode).toRfc4122();
-
-            // replace the bytes at the end of the packet for the connection secret between these nodes
-            addNodePacket->write(rfcConnectionSecret);
-
+        [this, &addNodePacket, connectionSecretIndex, addedNode, limitedNodeListWeak](const SharedNodePointer& node) {
             // send off this packet to the node
-            limitedNodeList->sendUnreliablePacket(*addNodePacket, *node);
+            auto limitedNodeList = limitedNodeListWeak.lock();
+            if (limitedNodeList) {
+                addNodePacket->seek(connectionSecretIndex);
+
+                QByteArray rfcConnectionSecret = connectionSecretForNodes(node, addedNode).toRfc4122();
+
+                // replace the bytes at the end of the packet for the connection secret between these nodes
+                addNodePacket->write(rfcConnectionSecret);
+
+                limitedNodeList->sendUnreliablePacket(*addNodePacket, *node);
+            }
         }
     );
 }
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index ca2d9a919e..ed92a3bd7d 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -1138,8 +1138,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
 
     // setup a timer for domain-server check ins
     QTimer* domainCheckInTimer = new QTimer(this);
-    connect(domainCheckInTimer, &QTimer::timeout, [this, &nodeList] {
-        if (!isServerlessMode()) {
+    QWeakPointer<NodeList> nodeListWeak = nodeList;
+    connect(domainCheckInTimer, &QTimer::timeout, [this, nodeListWeak] {
+        auto nodeList = nodeListWeak.lock();
+        if (!isServerlessMode() && nodeList) {
             nodeList->sendDomainServerCheckIn();
         }
     });
diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp
index eb96554cb2..01c9872cd7 100644
--- a/interface/src/avatar/AvatarManager.cpp
+++ b/interface/src/avatar/AvatarManager.cpp
@@ -333,16 +333,21 @@ void AvatarManager::postUpdate(float deltaTime, const render::ScenePointer& scen
 
 void AvatarManager::sendIdentityRequest(const QUuid& avatarID) const {
     auto nodeList = DependencyManager::get<NodeList>();
+    QWeakPointer<NodeList> nodeListWeak = nodeList;
     nodeList->eachMatchingNode(
         [](const SharedNodePointer& node)->bool {
-        return node->getType() == NodeType::AvatarMixer && node->getActiveSocket();
-    },
-        [this, avatarID, &nodeList](const SharedNodePointer& node) {
-        auto packet = NLPacket::create(PacketType::AvatarIdentityRequest, NUM_BYTES_RFC4122_UUID, true);
-        packet->write(avatarID.toRfc4122());
-        nodeList->sendPacket(std::move(packet), *node);
-        ++_identityRequestsSent;
-    });
+            return node->getType() == NodeType::AvatarMixer && node->getActiveSocket();
+        },
+        [this, avatarID, nodeListWeak](const SharedNodePointer& node) {
+            auto nodeList = nodeListWeak.lock();
+            if (nodeList) {
+                auto packet = NLPacket::create(PacketType::AvatarIdentityRequest, NUM_BYTES_RFC4122_UUID, true);
+                packet->write(avatarID.toRfc4122());
+                nodeList->sendPacket(std::move(packet), *node);
+                ++_identityRequestsSent;
+            }
+        }
+    );
 }
 
 void AvatarManager::simulateAvatarFades(float deltaTime) {
diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp
index 37f94f5b2a..438ea775af 100644
--- a/interface/src/ui/PreferencesDialog.cpp
+++ b/interface/src/ui/PreferencesDialog.cpp
@@ -416,12 +416,24 @@ void setupPreferences() {
     {
         static const QString NETWORKING("Networking");
 
-        auto nodelist = DependencyManager::get<NodeList>();
+        QWeakPointer<NodeList> nodeListWeak = DependencyManager::get<NodeList>();
         {
             static const int MIN_PORT_NUMBER { 0 };
             static const int MAX_PORT_NUMBER { 65535 };
-            auto getter = [&nodelist] { return static_cast<int>(nodelist->getSocketLocalPort()); };
-            auto setter = [&nodelist](int preset) { nodelist->setSocketLocalPort(static_cast<quint16>(preset)); };
+            auto getter = [nodeListWeak] {
+                auto nodeList = nodeListWeak.lock();
+                if (nodeList) {
+                    return static_cast<int>(nodeList->getSocketLocalPort());
+                } else {
+                    return -1;
+                }
+            };
+            auto setter = [nodeListWeak](int preset) {
+                auto nodeList = nodeListWeak.lock();
+                if (nodeList) {
+                    nodeList->setSocketLocalPort(static_cast<quint16>(preset));
+                }
+            };
             auto preference = new IntSpinnerPreference(NETWORKING, "Listening Port", getter, setter);
             preference->setMin(MIN_PORT_NUMBER);
             preference->setMax(MAX_PORT_NUMBER);
diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp
index dfb825411d..2d22f90d1a 100644
--- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp
+++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp
@@ -331,7 +331,7 @@ void OffscreenQmlSurface::onRootCreated() {
     getSurfaceContext()->setContextProperty("offscreenWindow", QVariant::fromValue(getWindow()));
 
     // Connect with the audio client and listen for audio device changes
-    connect(DependencyManager::get<AudioClient>().data(), &AudioClient::deviceChanged, this, [&](QAudio::Mode mode, const QAudioDeviceInfo& device) {
+    connect(DependencyManager::get<AudioClient>().data(), &AudioClient::deviceChanged, this, [this](QAudio::Mode mode, const QAudioDeviceInfo& device) {
         if (mode == QAudio::Mode::AudioOutput) {
             QMetaObject::invokeMethod(this, "changeAudioOutputDevice", Qt::QueuedConnection, Q_ARG(QString, device.deviceName()));
         }