From 55b4784a02969adbe4d7f4ae0ae44af41c720d9f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 22 Jul 2015 13:52:49 -0700 Subject: [PATCH] avoid entity-server node/octree deadlock on shutdown --- assignment-client/src/octree/OctreeSendThread.h | 2 +- assignment-client/src/octree/OctreeServer.cpp | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/assignment-client/src/octree/OctreeSendThread.h b/assignment-client/src/octree/OctreeSendThread.h index 78f480b5eb..f22d63611c 100644 --- a/assignment-client/src/octree/OctreeSendThread.h +++ b/assignment-client/src/octree/OctreeSendThread.h @@ -42,7 +42,7 @@ protected: virtual bool process(); private: - OctreeServer* _myServer; + QPointer _myServer; SharedNodePointer _node; QUuid _nodeUUID; diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index f5d599b5d3..c018d65f98 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -1175,13 +1175,22 @@ void OctreeServer::aboutToFinish() { if (_jurisdictionSender) { _jurisdictionSender->terminating(); } + + QSet nodesToKill; - // force a shutdown of all of our OctreeSendThreads - at this point it has to be impossible for a - // linkedDataCreateCallback to be called for a new node - nodeList->eachNode([this](const SharedNodePointer& node) { + // Force a shutdown of all of our OctreeSendThreads. + // At this point it has to be impossible for a linkedDataCreateCallback to be called for a new node + nodeList->eachNode([&nodesToKill](const SharedNodePointer& node) { + nodesToKill << node; + }); + + // What follows is a hack to force OctreeSendThreads to cleanup before the OctreeServer is gone. + // I would prefer to allow the SharedNodePointer ref count drop to zero to do this automatically + // but that isn't possible as long as the OctreeSendThread has an OctreeServer* that it uses. + for (auto& node : nodesToKill) { qDebug() << qPrintable(_safeServerName) << "server about to finish while node still connected node:" << *node; forceNodeShutdown(node); - }); + } if (_persistThread) { _persistThread->aboutToFinish();