* 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.
0.6.1-post-fixes
Adam Frisby 2008-11-08 20:52:48 +00:00
parent cbda728183
commit fb2a1a6b7c
3 changed files with 67 additions and 30 deletions

View File

@ -111,5 +111,14 @@ namespace OpenSim.Framework
return m_queue.ToArray(); return m_queue.ToArray();
} }
} }
public void Clear()
{
lock(m_queueSync)
{
m_pqueue.Clear();
m_queue.Clear();
}
}
} }
} }

View File

@ -98,7 +98,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// A list of the packets we haven't acked yet // A list of the packets we haven't acked yet
// //
private Dictionary<uint,uint> m_PendingAcks = new Dictionary<uint,uint>(); private Dictionary<uint, uint> m_PendingAcks = new Dictionary<uint, uint>();
// Dictionary of the packets that need acks from the client. // Dictionary of the packets that need acks from the client.
// //
@ -234,6 +234,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_AckTimer.Stop(); m_AckTimer.Stop();
m_PacketQueue.Enqueue(null); m_PacketQueue.Enqueue(null);
m_PacketQueue.Close();
} }
// Send one packet. This actually doesn't send anything, it queues // Send one packet. This actually doesn't send anything, it queues
@ -767,33 +768,41 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// If we sent a killpacket // If we sent a killpacket
if (packet is 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, Abort();
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); // 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();
} }
} }
} }

View File

@ -131,7 +131,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
userSettings.ClientThrottleMultipler); userSettings.ClientThrottleMultipler);
throttleTimer = new Timer((int) (throttletimems/throttleTimeDivisor)); throttleTimer = new Timer((int) (throttletimems/throttleTimeDivisor));
throttleTimer.Elapsed += new ElapsedEventHandler(ThrottleTimerElapsed); throttleTimer.Elapsed += ThrottleTimerElapsed;
throttleTimer.Start(); throttleTimer.Start();
// TIMERS needed for this // 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() public void Close()
{ {
m_log.Info("[PACKETQUEUE] Close called");
Flush(); Flush();
WipeClean(); // I'm sure there's a dirty joke in here somewhere. -AFrisby
m_enabled = false; m_enabled = false;
throttleTimer.Stop(); throttleTimer.Stop();