diff options
Diffstat (limited to '')
-rw-r--r-- | src/ClientHandle.cpp | 3 | ||||
-rw-r--r-- | src/ClientHandle.h | 7 | ||||
-rw-r--r-- | src/Server.cpp | 21 |
3 files changed, 22 insertions, 9 deletions
diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 01d85fee8..f49304ebe 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -66,6 +66,7 @@ cClientHandle::cClientHandle(const AString & a_IPString, int a_ViewDistance) : m_CurrentViewDistance(a_ViewDistance), m_RequestedViewDistance(a_ViewDistance), m_IPString(a_IPString), + m_ShouldDestroyPlayer(true), m_Protocol(this), m_Player(nullptr), // In order to catch when client leaves before authentication m_TicksSinceLastPacket(0), @@ -105,7 +106,7 @@ cClientHandle::~cClientHandle() ASSERT(m_State == eState::csDestroyed); // Has Destroy() been called? if ( - !cRoot::Get()->GetServer()->IsShuttingDown() && // If server is shutting down, m_Player is considered invalid. It will be cleaned up by cWorld + m_ShouldDestroyPlayer && // If server is shutting down, m_Player is considered invalid. It will be cleaned up by cWorld (m_Player != nullptr) ) { diff --git a/src/ClientHandle.h b/src/ClientHandle.h index bb90db777..78caa9532 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -375,6 +375,9 @@ public: // tolua_export /** Called by the protocol recognizer when the protocol version is known. */ void SetProtocolVersion(UInt32 a_ProtocolVersion) { m_ProtocolVersion = a_ProtocolVersion; } + /** Called by cServer::Shutdown to indicate m_Player's destruction is out of our control */ + void StopPlayerDestructionManagement() { m_ShouldDestroyPlayer = false; } + /** Returns the protocol version number of the protocol that the client is talking. Returns zero if the protocol version is not (yet) known. */ UInt32 GetProtocolVersion(void) const { return m_ProtocolVersion; } // tolua_export @@ -411,6 +414,10 @@ private: AString m_Username; Json::Value m_Properties; + /** Flag indicating whether it is safe to access m_Player in our destructor to destroy it + While used inter-thread, atomicity not necessary as is only ever set in the main thread and read in a destructor, which is not called as long as someone has a reference to us */ + bool m_ShouldDestroyPlayer; + struct sChunkCoordsHash { size_t operator()(const cChunkCoords & a_ChunkCoords) const diff --git a/src/Server.cpp b/src/Server.cpp index ca2de01a4..33d94e639 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -660,6 +660,16 @@ void cServer::BindBuiltInConsoleCommands(void) void cServer::Shutdown(void) { + { + // Notify all clients of the shutdown: + cCSLock Lock(m_CSClients); + for (const auto & Client : m_Clients) + { + Client->StopPlayerDestructionManagement(); + // TODO: send "Server shut down: kthnxbai!" + } + } + // Stop listening on all sockets: for (auto srv: m_ServerHandles) { @@ -667,19 +677,14 @@ void cServer::Shutdown(void) } m_ServerHandles.clear(); + // At this point, OnRemoteClosed will eventually be called for the clienthandle before it is deleted + // No need to manually call Destroy + // Notify the tick thread and wait for it to terminate: m_bRestarting = true; m_RestartEvent.Wait(); cRoot::Get()->SaveAllChunks(); - - // Remove all clients: - cCSLock Lock(m_CSClients); - for (auto itr = m_Clients.begin(); itr != m_Clients.end(); ++itr) - { - (*itr)->SetState(cClientHandle::eState::csDestroyed); - // TODO: send "Server shut down: kthnxbai!" - } } |