From e34f097543c7a2b733a6d6a8b55a26a6777b5e83 Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Sun, 11 Nov 2012 14:00:58 +0000 Subject: Hopefully a fix for crash when chunks are added to a client being destroyed. git-svn-id: http://mc-server.googlecode.com/svn/trunk@1032 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/Bindings.cpp | 8 ++++---- source/Bindings.h | 2 +- source/ClientHandle.cpp | 25 +++++++++++++++++++++---- source/ClientHandle.h | 20 +++++++++++--------- 4 files changed, 37 insertions(+), 18 deletions(-) (limited to 'source') diff --git a/source/Bindings.cpp b/source/Bindings.cpp index 40c5d719a..ed082c93e 100644 --- a/source/Bindings.cpp +++ b/source/Bindings.cpp @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 11/01/12 22:24:07. +** Generated automatically by tolua++-1.0.92 on 11/11/12 14:50:43. */ #ifndef __cplusplus @@ -3882,14 +3882,14 @@ static int tolua_AllToLua_cClientHandle_GetViewDistance00(lua_State* tolua_S) #ifndef TOLUA_RELEASE tolua_Error tolua_err; if ( - !tolua_isusertype(tolua_S,1,"cClientHandle",0,&tolua_err) || + !tolua_isusertype(tolua_S,1,"const cClientHandle",0,&tolua_err) || !tolua_isnoobj(tolua_S,2,&tolua_err) ) goto tolua_lerror; else #endif { - cClientHandle* self = (cClientHandle*) tolua_tousertype(tolua_S,1,0); + const cClientHandle* self = (const cClientHandle*) tolua_tousertype(tolua_S,1,0); #ifndef TOLUA_RELEASE if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetViewDistance'", NULL); #endif @@ -11542,7 +11542,7 @@ static int tolua_AllToLua_cWorld_SetWorldTime00(lua_State* tolua_S) #endif { cWorld* self = (cWorld*) tolua_tousertype(tolua_S,1,0); - long long a_TimeOfDay = ((long long) tolua_tonumber(tolua_S,2,0)); + long long a_TimeOfDay = (( long long) tolua_tonumber(tolua_S,2,0)); #ifndef TOLUA_RELEASE if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetWorldTime'", NULL); #endif diff --git a/source/Bindings.h b/source/Bindings.h index 42e495fe5..53d1d69fa 100644 --- a/source/Bindings.h +++ b/source/Bindings.h @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 11/01/12 22:24:07. +** Generated automatically by tolua++-1.0.92 on 11/11/12 14:50:43. */ /* Exported function */ diff --git a/source/ClientHandle.cpp b/source/ClientHandle.cpp index 24654d303..fd7ad917e 100644 --- a/source/ClientHandle.cpp +++ b/source/ClientHandle.cpp @@ -78,7 +78,6 @@ cClientHandle::cClientHandle(const cSocket * a_Socket, int a_ViewDistance) : m_ViewDistance(a_ViewDistance) , m_IPString(a_Socket->GetIPString()) , m_OutgoingData(64 KiB) - , m_bDestroyed(false) , m_Player(NULL) , m_bKicking(false) , m_TimeSinceLastPacket(0) @@ -109,6 +108,8 @@ cClientHandle::cClientHandle(const cSocket * a_Socket, int a_ViewDistance) cClientHandle::~cClientHandle() { + ASSERT(m_State == csDestroyed); // Has Destroy() been called? + LOGD("Deleting client \"%s\" at %p", GetUsername().c_str(), this); // Remove from cSocketThreads, we're not to be called anymore: @@ -178,13 +179,13 @@ void cClientHandle::Destroy() // otherwise the destructor may be called within another thread before the client is removed from chunks // http://forum.mc-server.org/showthread.php?tid=366 + m_State = csDestroying; if ((m_Player != NULL) && (m_Player->GetWorld() != NULL)) { RemoveFromAllChunks(); m_Player->GetWorld()->RemoveClientFromChunkSender(this); } - - m_bDestroyed = true; + m_State = csDestroyed; } @@ -268,7 +269,7 @@ void cClientHandle::Authenticate(void) void cClientHandle::StreamChunks(void) { - if (m_State < csAuthenticating) + if ((m_State < csAuthenticating) || (m_State >= csDestroying)) { return; } @@ -367,6 +368,12 @@ void cClientHandle::StreamChunks(void) void cClientHandle::StreamChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ) { + if (m_State >= csDestroying) + { + // Don't stream chunks to clients that are being destroyed + return; + } + cWorld * World = m_Player->GetWorld(); ASSERT(World != NULL); @@ -1644,6 +1651,11 @@ void cClientHandle::SetViewDistance(int a_ViewDistance) bool cClientHandle::WantsSendChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ) { + if (m_State >= csDestroying) + { + return false; + } + cCSLock Lock(m_CSChunkLists); return (std::find(m_ChunksToSend.begin(), m_ChunksToSend.end(), cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ)) != m_ChunksToSend.end()); } @@ -1654,6 +1666,11 @@ bool cClientHandle::WantsSendChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ) void cClientHandle::AddWantedChunk(int a_ChunkX, int a_ChunkZ) { + if (m_State >= csDestroying) + { + return; + } + LOGD("Adding chunk [%d, %d] to wanted chunks for client %p", a_ChunkX, a_ChunkZ, this); cCSLock Lock(m_CSChunkLists); if (std::find(m_ChunksToSend.begin(), m_ChunksToSend.end(), cChunkCoords(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ)) == m_ChunksToSend.end()) diff --git a/source/ClientHandle.h b/source/ClientHandle.h index a9a372186..ec79b3b71 100644 --- a/source/ClientHandle.h +++ b/source/ClientHandle.h @@ -69,14 +69,15 @@ public: // Removes the client from all chunks. Used when switching worlds or destroying the player void RemoveFromAllChunks(void); - inline bool IsLoggedIn(void) const { return m_State >= csAuthenticating; } + inline bool IsLoggedIn(void) const { return (m_State >= csAuthenticating); } void Tick(float a_Dt); - bool IsDestroyed() { return m_bDestroyed; } - void Destroy(); + void Destroy(void); - bool IsPlaying(void) const {return (m_State == csPlaying); } + bool IsPlaying (void) const { return (m_State == csPlaying); } + bool IsDestroyed (void) const { return (m_State == csDestroyed); } + bool IsDestroying(void) const { return (m_State == csDestroying); } void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType); void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); @@ -124,10 +125,10 @@ public: const AString & GetUsername(void) const; //tolua_export void SetUsername( const AString & a_Username ); //tolua_export - inline short GetPing() const { return m_Ping; } //tolua_export + inline short GetPing(void) const { return m_Ping; } //tolua_export - void SetViewDistance(int a_ViewDistance); //tolua_export - int GetViewDistance() { return m_ViewDistance; }//tolua_export + void SetViewDistance(int a_ViewDistance); // tolua_export + int GetViewDistance(void) const { return m_ViewDistance; } // tolua_export int GetUniqueID() const { return m_UniqueID; } //tolua_export @@ -199,7 +200,6 @@ private: Vector3d m_ConfirmPosition; - bool m_bDestroyed; cPlayer * m_Player; bool m_bKicking; @@ -230,8 +230,10 @@ private: csDownloadingWorld, // The client is waiting for chunks, we're waiting for the loader to provide and send them csConfirmingPos, // The client has been sent the position packet, waiting for them to repeat the position back csPlaying, // Normal gameplay + csDestroying, // The client is being destroyed, don't queue any more packets / don't add to chunks + csDestroyed, // The client has been destroyed, the destructor is to be called from the owner thread - // TODO: Add Kicking and Destroyed here as well + // TODO: Add Kicking here as well } ; eState m_State; -- cgit v1.2.3