From 7268a70902b04e098b6b530986d9ce6d210fdd07 Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Sun, 26 Feb 2012 12:55:42 +0000 Subject: Attempt at fixing crashes with disconnecting players git-svn-id: http://mc-server.googlecode.com/svn/trunk@329 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/cClientHandle.cpp | 8 ++++++++ source/cEntity.cpp | 16 ++++++++++------ source/cPlayer.cpp | 16 ++++++---------- source/cServer.cpp | 9 +++++++++ source/cServer.h | 4 +++- source/cSocketThreads.cpp | 3 ++- 6 files changed, 38 insertions(+), 18 deletions(-) (limited to 'source') diff --git a/source/cClientHandle.cpp b/source/cClientHandle.cpp index 41d2fda6c..4a6a0b508 100644 --- a/source/cClientHandle.cpp +++ b/source/cClientHandle.cpp @@ -165,6 +165,10 @@ cClientHandle::~cClientHandle() cPacket_Chat Left(m_Username + " left the game!"); World->Broadcast(Left, this); } + if (World != NULL) + { + World->RemovePlayer(m_Player); + } } if (m_Socket.IsValid()) @@ -209,6 +213,10 @@ cClientHandle::~cClientHandle() // Queue the socket to close as soon as it sends all outgoing data: cRoot::Get()->GetServer()->QueueClientClose(&m_Socket); + // We need to remove the socket from SocketThreads because we own it and it gets destroyed after this destructor finishes + // TODO: The socket needs to stay alive, someone else has to own it + cRoot::Get()->GetServer()->RemoveClient(&m_Socket); + LOG("ClientHandle at %p deleted", this); } diff --git a/source/cEntity.cpp b/source/cEntity.cpp index cb91c2bdc..3df995d59 100644 --- a/source/cEntity.cpp +++ b/source/cEntity.cpp @@ -169,14 +169,18 @@ void cEntity::MoveToCorrectChunk(bool a_bIgnoreOldChunk) void cEntity::Destroy() { - if( !m_bDestroyed ) + if (m_bDestroyed) { - m_bDestroyed = true; - if( !m_bRemovedFromChunk ) - { - RemoveFromChunk(); - } + return; } + if (!m_bRemovedFromChunk) + { + RemoveFromChunk(); + } + + m_World->BroadcastToChunk(m_ChunkX, m_ChunkY, m_ChunkZ, cPacket_DestroyEntity(this)); + + m_bDestroyed = true; } diff --git a/source/cPlayer.cpp b/source/cPlayer.cpp index 495cc6abf..7899fdc97 100644 --- a/source/cPlayer.cpp +++ b/source/cPlayer.cpp @@ -125,18 +125,14 @@ void cPlayer::Initialize( cWorld* a_World ) cPlayer::~cPlayer(void) { SaveToDisk(); - m_ClientHandle = 0; + m_ClientHandle = NULL; CloseWindow(-1); - if( m_Inventory ) - { - delete m_Inventory; - m_Inventory = 0; - } - if(m_CreativeInventory) - { - delete m_CreativeInventory; - } + delete m_Inventory; + m_Inventory = NULL; + + delete m_CreativeInventory; + delete m_pState; m_World->RemovePlayer( this ); } diff --git a/source/cServer.cpp b/source/cServer.cpp index b1dab21e5..ab4698f3f 100644 --- a/source/cServer.cpp +++ b/source/cServer.cpp @@ -134,6 +134,15 @@ void cServer::QueueClientClose(const cSocket * a_Socket) +void cServer::RemoveClient(const cSocket * a_Socket) +{ + m_SocketThreads.RemoveClient(a_Socket); +} + + + + + bool cServer::InitServer( int a_Port ) { if( m_bIsConnected ) diff --git a/source/cServer.h b/source/cServer.h index 200f2bb1f..5e21dbf37 100644 --- a/source/cServer.h +++ b/source/cServer.h @@ -58,7 +58,7 @@ public: //tolua_export const AString & GetServerID(void) const; - void ClientDestroying(const cClientHandle * a_Client); // Called by cClientHandle::Destroy(); removes the client from m_SocketThreads + void ClientDestroying(const cClientHandle * a_Client); // Called by cClientHandle::Destroy(); stop m_SocketThreads from calling back into a_Client void NotifyClientWrite(const cClientHandle * a_Client); // Notifies m_SocketThreads that client has something to be written @@ -66,6 +66,8 @@ public: //tolua_export void QueueClientClose(const cSocket * a_Socket); // Queues the socket to close when all its outgoing data is sent + void RemoveClient(const cSocket * a_Socket); // Removes the socket from m_SocketThreads + private: friend class cRoot; // so cRoot can create and destroy cServer diff --git a/source/cSocketThreads.cpp b/source/cSocketThreads.cpp index 5e98398c4..74324f909 100644 --- a/source/cSocketThreads.cpp +++ b/source/cSocketThreads.cpp @@ -87,7 +87,8 @@ void cSocketThreads::RemoveClient(const cSocket * a_Socket) } } // for itr - m_Threads[] - ASSERT(!"Removing an unknown socket"); + // Cannot assert here, this may actually happen legally, since cClientHandle has to clean up the socket and it may have already closed in the meantime + // ASSERT(!"Removing an unknown socket"); } -- cgit v1.2.3