aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMachiavelli <machiavelli.trinity@gmail.com>2011-12-19 21:12:35 +0100
committerMachiavelli <machiavelli.trinity@gmail.com>2011-12-19 21:12:35 +0100
commit8e0be985fdc841357606c07fd2992f767f1f00f4 (patch)
tree6c0c7c2c4da5254302bd75699042c98821436a6b
parentd1378a9c941dfa9ba15af4e95759984f6dc69726 (diff)
Core/Netcode: Fix a possible infinite loop after 829be0b82 (which was accidentally merged in this morning)
-rwxr-xr-xsrc/server/game/Server/WorldSession.cpp16
-rwxr-xr-xsrc/server/shared/Threading/LockedQueue.h7
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;
}