summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/ClientHandle.cpp3
-rw-r--r--src/ClientHandle.h7
-rw-r--r--src/Server.cpp21
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!"
- }
}