diff options
author | Machiavelli <machiavelli.trinity@gmail.com> | 2011-12-19 21:12:35 +0100 |
---|---|---|
committer | Machiavelli <machiavelli.trinity@gmail.com> | 2011-12-19 21:12:35 +0100 |
commit | 8e0be985fdc841357606c07fd2992f767f1f00f4 (patch) | |
tree | 6c0c7c2c4da5254302bd75699042c98821436a6b | |
parent | d1378a9c941dfa9ba15af4e95759984f6dc69726 (diff) |
Core/Netcode: Fix a possible infinite loop after 829be0b82 (which was accidentally merged in this morning)
-rwxr-xr-x | src/server/game/Server/WorldSession.cpp | 16 | ||||
-rwxr-xr-x | src/server/shared/Threading/LockedQueue.h | 7 |
2 files changed, 19 insertions, 4 deletions
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index be6f152d891..57844f53aa3 100755 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -224,7 +224,17 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) WorldPacket* packet = NULL; //! Delete packet after processing by default bool deletePacket = true; - while (m_Socket && !m_Socket->IsClosed() && _recvQueue.next(packet, updater)) + //! To prevent infinite loop + bool delayedPackets = false; + WorldPacket* firstDelayedPacket = NULL; + //! If _recvQueue.peek() == firstDelayedPacket it means that in this Update call, we've processed all + //! *properly timed* packets, and we're now at the part of the queue where we find + //! delayed packets that were re-enqueued due to improper timing. To prevent an infinite + //! loop caused by re-enqueueing the same packets over and over again, we stop updating this session + //! and continue updating others. The re-enqueued packets will be handled in the next Update call for this session. + while (m_Socket && !m_Socket->IsClosed() && + !_recvQueue.empty() && _recvQueue.peek(true) != firstDelayedPacket && + _recvQueue.next(packet, updater)) { if (packet->GetOpcode() >= NUM_MSG_TYPES) { @@ -246,9 +256,11 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) //! the client to be in world yet. We will re-add the packets to the bottom of the queue and process them later. if (!m_playerRecentlyLogout) { + //! Prevent infinite loop + if (!firstDelayedPacket) + firstDelayedPacket = packet; //! Because checking a bool is faster than reallocating memory deletePacket = false; - //! Re-enqueue QueuePacket(packet); //! Log sLog->outDebug(LOG_FILTER_NETWORKIO, "Re-enqueueing packet with opcode %s (0x%.4X) with with status STATUS_LOGGEDIN. " diff --git a/src/server/shared/Threading/LockedQueue.h b/src/server/shared/Threading/LockedQueue.h index 92eab440684..4d2ddd33f5f 100755 --- a/src/server/shared/Threading/LockedQueue.h +++ b/src/server/shared/Threading/LockedQueue.h @@ -98,13 +98,16 @@ namespace ACE_Based return true; } - //! Peeks at the top of the queue. Remember to unlock after use. - T& peek() + //! Peeks at the top of the queue. Check if the queue is empty before calling! Remember to unlock after use if autoUnlock == false. + T& peek(bool autoUnlock = false) { lock(); T& result = _queue.front(); + if (autoUnlock) + unlock(); + return result; } |