From fb2a1a6b7cc65352644921bc7c7b7745ca7d2560 Mon Sep 17 00:00:00 2001 From: Adam Frisby Date: Sat, 8 Nov 2008 20:52:48 +0000 Subject: [PATCH] * Fixed a major memory leak in packet processing - PacketQueue.Close is never called, causing the PacketQueue for dead clients to be preserved (including it's contents). * This patch is highly experimental and may cause clients to not be able to connect, if this is the case, it will be rolled back in approximately 5 minutes. --- OpenSim/Framework/BlockingQueue.cs | 9 +++ .../ClientStack/LindenUDP/LLPacketHandler.cs | 67 +++++++++++-------- .../ClientStack/LindenUDP/LLPacketQueue.cs | 21 +++++- 3 files changed, 67 insertions(+), 30 deletions(-) diff --git a/OpenSim/Framework/BlockingQueue.cs b/OpenSim/Framework/BlockingQueue.cs index 6fbf88fd35..0329e0f2fe 100644 --- a/OpenSim/Framework/BlockingQueue.cs +++ b/OpenSim/Framework/BlockingQueue.cs @@ -111,5 +111,14 @@ namespace OpenSim.Framework return m_queue.ToArray(); } } + + public void Clear() + { + lock(m_queueSync) + { + m_pqueue.Clear(); + m_queue.Clear(); + } + } } } diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs index cce3399989..7a66925664 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs @@ -98,8 +98,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP // A list of the packets we haven't acked yet // - private Dictionary m_PendingAcks = new Dictionary(); - + private Dictionary m_PendingAcks = new Dictionary(); + // Dictionary of the packets that need acks from the client. // private class AckData @@ -117,7 +117,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public int TickCount; public int Resends; } - + private Dictionary m_NeedAck = new Dictionary(); @@ -234,6 +234,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_AckTimer.Stop(); m_PacketQueue.Enqueue(null); + m_PacketQueue.Close(); } // Send one packet. This actually doesn't send anything, it queues @@ -362,7 +363,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if ((now - data.TickCount) > m_ResendTimeout) { m_NeedAck[packet.Header.Sequence].Resends++; - + // The client needs to be told that a packet is being resent, otherwise it appears to believe // that it should reset its sequence to that packet number. packet.Header.Resent = true; @@ -767,33 +768,41 @@ namespace OpenSim.Region.ClientStack.LindenUDP // If we sent a killpacket if (packet is KillPacket) - Thread.CurrentThread.Abort(); - - // Actually make the byte array and send it - byte[] sendbuffer = packet.ToBytes(); - - //m_log.DebugFormat( - // "[CLIENT]: In {0} sending packet {1}", - // m_Client.Scene.RegionInfo.ExternalEndPoint.Port, packet.Header.Sequence); - - if (packet.Header.Zerocoded) { - int packetsize = Helpers.ZeroEncode(sendbuffer, - sendbuffer.Length, m_ZeroOutBuffer); - m_PacketServer.SendPacketTo(m_ZeroOutBuffer, packetsize, - SocketFlags.None, m_Client.CircuitCode); - } - else - { - // Need some extra space in case we need to add proxy - // information to the message later - Buffer.BlockCopy(sendbuffer, 0, m_ZeroOutBuffer, 0, - sendbuffer.Length); - m_PacketServer.SendPacketTo(m_ZeroOutBuffer, - sendbuffer.Length, SocketFlags.None, m_Client.CircuitCode); - } + Abort(); - PacketPool.Instance.ReturnPacket(packet); + // Actually make the byte array and send it + byte[] sendbuffer = packet.ToBytes(); + + //m_log.DebugFormat( + // "[CLIENT]: In {0} sending packet {1}", + // m_Client.Scene.RegionInfo.ExternalEndPoint.Port, packet.Header.Sequence); + + if (packet.Header.Zerocoded) + { + int packetsize = Helpers.ZeroEncode(sendbuffer, + sendbuffer.Length, m_ZeroOutBuffer); + m_PacketServer.SendPacketTo(m_ZeroOutBuffer, packetsize, + SocketFlags.None, m_Client.CircuitCode); + } + else + { + // Need some extra space in case we need to add proxy + // information to the message later + Buffer.BlockCopy(sendbuffer, 0, m_ZeroOutBuffer, 0, + sendbuffer.Length); + m_PacketServer.SendPacketTo(m_ZeroOutBuffer, + sendbuffer.Length, SocketFlags.None, m_Client.CircuitCode); + } + + PacketPool.Instance.ReturnPacket(packet); + } + } + + private void Abort() + { + m_PacketQueue.Close(); + Thread.CurrentThread.Abort(); } } } diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs index 9aa27ec30c..bb2d270c8d 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs @@ -131,7 +131,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP userSettings.ClientThrottleMultipler); throttleTimer = new Timer((int) (throttletimems/throttleTimeDivisor)); - throttleTimer.Elapsed += new ElapsedEventHandler(ThrottleTimerElapsed); + throttleTimer.Elapsed += ThrottleTimerElapsed; throttleTimer.Start(); // TIMERS needed for this @@ -256,9 +256,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } + public void WipeClean() + { + m_log.Info("[PACKETQUEUE] Wiping Packet Queues Clean"); + lock(this) + { + ResendOutgoingPacketQueue.Clear(); + LandOutgoingPacketQueue.Clear(); + WindOutgoingPacketQueue.Clear(); + CloudOutgoingPacketQueue.Clear(); + TaskOutgoingPacketQueue.Clear(); + TaskLowpriorityPacketQueue.Clear(); + TextureOutgoingPacketQueue.Clear(); + AssetOutgoingPacketQueue.Clear(); + SendQueue.Clear(); + } + } + public void Close() { + m_log.Info("[PACKETQUEUE] Close called"); Flush(); + WipeClean(); // I'm sure there's a dirty joke in here somewhere. -AFrisby m_enabled = false; throttleTimer.Stop();