mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-07-24 02:14:09 +02:00
fixes to voxel server crashes on client shutdown
This commit is contained in:
parent
23d54a0f5f
commit
3cb3cb81c4
6 changed files with 50 additions and 19 deletions
|
@ -67,6 +67,14 @@ OctreeQueryNode::~OctreeQueryNode() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OctreeQueryNode::deleteLater() {
|
||||||
|
_isShuttingDown = true;
|
||||||
|
if (_octreeSendThread) {
|
||||||
|
_octreeSendThread->setIsShuttingDown();
|
||||||
|
}
|
||||||
|
OctreeQuery::deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void OctreeQueryNode::initializeOctreeSendThread(OctreeServer* octreeServer, const QUuid& nodeUUID) {
|
void OctreeQueryNode::initializeOctreeSendThread(OctreeServer* octreeServer, const QUuid& nodeUUID) {
|
||||||
// Create octree sending thread...
|
// Create octree sending thread...
|
||||||
|
|
|
@ -27,6 +27,7 @@ class OctreeQueryNode : public OctreeQuery {
|
||||||
public:
|
public:
|
||||||
OctreeQueryNode();
|
OctreeQueryNode();
|
||||||
virtual ~OctreeQueryNode();
|
virtual ~OctreeQueryNode();
|
||||||
|
virtual void deleteLater();
|
||||||
|
|
||||||
void init(); // called after creation to set up some virtual items
|
void init(); // called after creation to set up some virtual items
|
||||||
virtual PacketType getMyPacketType() const = 0;
|
virtual PacketType getMyPacketType() const = 0;
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <QMutexLocker>
|
||||||
|
|
||||||
#include <NodeList.h>
|
#include <NodeList.h>
|
||||||
#include <PacketHeaders.h>
|
#include <PacketHeaders.h>
|
||||||
#include <PerfStat.h>
|
#include <PerfStat.h>
|
||||||
|
@ -21,7 +23,9 @@ OctreeSendThread::OctreeSendThread(const QUuid& nodeUUID, OctreeServer* myServer
|
||||||
_nodeUUID(nodeUUID),
|
_nodeUUID(nodeUUID),
|
||||||
_myServer(myServer),
|
_myServer(myServer),
|
||||||
_packetData(),
|
_packetData(),
|
||||||
_nodeMissingCount(0)
|
_nodeMissingCount(0),
|
||||||
|
_processLock(),
|
||||||
|
_isShuttingDown(false)
|
||||||
{
|
{
|
||||||
QString safeServerName("Octree");
|
QString safeServerName("Octree");
|
||||||
if (_myServer) {
|
if (_myServer) {
|
||||||
|
@ -43,8 +47,19 @@ OctreeSendThread::~OctreeSendThread() {
|
||||||
OctreeServer::clientDisconnected();
|
OctreeServer::clientDisconnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OctreeSendThread::setIsShuttingDown() {
|
||||||
|
QMutexLocker locker(&_processLock); // this will cause us to wait till the process loop is complete
|
||||||
|
_isShuttingDown = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool OctreeSendThread::process() {
|
bool OctreeSendThread::process() {
|
||||||
|
QMutexLocker locker(&_processLock);
|
||||||
|
|
||||||
|
if (_isShuttingDown) {
|
||||||
|
return false; // exit early if we're shutting down
|
||||||
|
}
|
||||||
|
|
||||||
const int MAX_NODE_MISSING_CHECKS = 10;
|
const int MAX_NODE_MISSING_CHECKS = 10;
|
||||||
if (_nodeMissingCount > MAX_NODE_MISSING_CHECKS) {
|
if (_nodeMissingCount > MAX_NODE_MISSING_CHECKS) {
|
||||||
qDebug() << "our target node:" << _nodeUUID << "has been missing the last" << _nodeMissingCount
|
qDebug() << "our target node:" << _nodeUUID << "has been missing the last" << _nodeMissingCount
|
||||||
|
@ -56,7 +71,10 @@ bool OctreeSendThread::process() {
|
||||||
|
|
||||||
// don't do any send processing until the initial load of the octree is complete...
|
// don't do any send processing until the initial load of the octree is complete...
|
||||||
if (_myServer->isInitialLoadComplete()) {
|
if (_myServer->isInitialLoadComplete()) {
|
||||||
SharedNodePointer node = NodeList::getInstance()->nodeWithUUID(_nodeUUID);
|
|
||||||
|
// see if we can get access to our node, but don't wait on the lock, if the nodeList is busy
|
||||||
|
// it might not return a node that is known, but that's ok we can handle that case.
|
||||||
|
SharedNodePointer node = NodeList::getInstance()->nodeWithUUID(_nodeUUID, false);
|
||||||
|
|
||||||
if (node) {
|
if (node) {
|
||||||
_nodeMissingCount = 0;
|
_nodeMissingCount = 0;
|
||||||
|
@ -113,19 +131,6 @@ int OctreeSendThread::handlePacketSend(const SharedNodePointer& node,
|
||||||
bool packetSent = false; // did we send a packet?
|
bool packetSent = false; // did we send a packet?
|
||||||
int packetsSent = 0;
|
int packetsSent = 0;
|
||||||
|
|
||||||
// double check that the node has an active socket, otherwise, don't send...
|
|
||||||
|
|
||||||
quint64 lockWaitStart = usecTimestampNow();
|
|
||||||
QMutexLocker locker(&node->getMutex());
|
|
||||||
quint64 lockWaitEnd = usecTimestampNow();
|
|
||||||
float lockWaitElapsedUsec = (float)(lockWaitEnd - lockWaitStart);
|
|
||||||
OctreeServer::trackNodeWaitTime(lockWaitElapsedUsec);
|
|
||||||
|
|
||||||
const HifiSockAddr* nodeAddress = node->getActiveSocket();
|
|
||||||
if (!nodeAddress) {
|
|
||||||
return packetsSent; // without sending...
|
|
||||||
}
|
|
||||||
|
|
||||||
// Here's where we check to see if this packet is a duplicate of the last packet. If it is, we will silently
|
// Here's where we check to see if this packet is a duplicate of the last packet. If it is, we will silently
|
||||||
// obscure the packet and not send it. This allows the callers and upper level logic to not need to know about
|
// obscure the packet and not send it. This allows the callers and upper level logic to not need to know about
|
||||||
// this rate control savings.
|
// this rate control savings.
|
||||||
|
|
|
@ -24,6 +24,8 @@ public:
|
||||||
OctreeSendThread(const QUuid& nodeUUID, OctreeServer* myServer);
|
OctreeSendThread(const QUuid& nodeUUID, OctreeServer* myServer);
|
||||||
virtual ~OctreeSendThread();
|
virtual ~OctreeSendThread();
|
||||||
|
|
||||||
|
void setIsShuttingDown();
|
||||||
|
|
||||||
static quint64 _totalBytes;
|
static quint64 _totalBytes;
|
||||||
static quint64 _totalWastedBytes;
|
static quint64 _totalWastedBytes;
|
||||||
static quint64 _totalPackets;
|
static quint64 _totalPackets;
|
||||||
|
@ -45,6 +47,8 @@ private:
|
||||||
OctreePacketData _packetData;
|
OctreePacketData _packetData;
|
||||||
|
|
||||||
int _nodeMissingCount;
|
int _nodeMissingCount;
|
||||||
|
QMutex _processLock; // don't allow us to have our nodeData, or our thread to be deleted while we're processing
|
||||||
|
bool _isShuttingDown;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __octree_server__OctreeSendThread__
|
#endif // __octree_server__OctreeSendThread__
|
||||||
|
|
|
@ -308,9 +308,21 @@ int NodeList::findNodeAndUpdateWithDataFromPacket(const QByteArray& packet) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedNodePointer NodeList::nodeWithUUID(const QUuid& nodeUUID) {
|
SharedNodePointer NodeList::nodeWithUUID(const QUuid& nodeUUID, bool blockingLock) {
|
||||||
|
SharedNodePointer node;
|
||||||
|
// if caller wants us to block and guarantee the correct answer, then honor that request
|
||||||
|
if (blockingLock) {
|
||||||
|
// this will block till we can get access
|
||||||
QMutexLocker locker(&_nodeHashMutex);
|
QMutexLocker locker(&_nodeHashMutex);
|
||||||
return _nodeHash.value(nodeUUID);
|
node = _nodeHash.value(nodeUUID);
|
||||||
|
} else {
|
||||||
|
// some callers are willing to get wrong answers but not block
|
||||||
|
if (_nodeHashMutex.tryLock()) {
|
||||||
|
node = _nodeHash.value(nodeUUID);
|
||||||
|
_nodeHashMutex.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedNodePointer NodeList::sendingNodeForPacket(const QByteArray& packet) {
|
SharedNodePointer NodeList::sendingNodeForPacket(const QByteArray& packet) {
|
||||||
|
|
|
@ -101,7 +101,8 @@ public:
|
||||||
QByteArray constructPingReplyPacket(const QByteArray& pingPacket);
|
QByteArray constructPingReplyPacket(const QByteArray& pingPacket);
|
||||||
void pingPublicAndLocalSocketsForInactiveNode(const SharedNodePointer& node);
|
void pingPublicAndLocalSocketsForInactiveNode(const SharedNodePointer& node);
|
||||||
|
|
||||||
SharedNodePointer nodeWithUUID(const QUuid& nodeUUID);
|
/// passing false for blockingLock, will tryLock, and may return NULL when a node with the UUID actually does exist
|
||||||
|
SharedNodePointer nodeWithUUID(const QUuid& nodeUUID, bool blockingLock = true);
|
||||||
SharedNodePointer sendingNodeForPacket(const QByteArray& packet);
|
SharedNodePointer sendingNodeForPacket(const QByteArray& packet);
|
||||||
|
|
||||||
SharedNodePointer addOrUpdateNode(const QUuid& uuid, char nodeType,
|
SharedNodePointer addOrUpdateNode(const QUuid& uuid, char nodeType,
|
||||||
|
|
Loading…
Reference in a new issue