From: Forest Date: Thu, 6 Jun 2019 21:20:56 +0000 (-0700) Subject: Clean up a slow leak of ping packets when connections are dispose X-Git-Tag: 1.0.0~44 X-Git-Url: https://git.deb.at/?a=commitdiff_plain;h=b554c1ef6017219f2710df4265a4108de1cbf4ad;p=rhonda%2Fimpostor.hazel.git Clean up a slow leak of ping packets when connections are dispose --- diff --git a/Hazel/MessageReader.cs b/Hazel/MessageReader.cs index f73fa49..1914437 100644 --- a/Hazel/MessageReader.cs +++ b/Hazel/MessageReader.cs @@ -1,10 +1,6 @@ using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; using System.Runtime.CompilerServices; using System.Text; -using System.Threading; namespace Hazel { diff --git a/Hazel/ObjectPool.cs b/Hazel/ObjectPool.cs index 0da7dbf..1b48415 100644 --- a/Hazel/ObjectPool.cs +++ b/Hazel/ObjectPool.cs @@ -15,23 +15,22 @@ namespace Hazel { private int numberCreated; public int NumberCreated { get { return numberCreated; } } + public int NumberInUse { get { return this.inuse.Count; } } + public int NumberNotInUse { get { return this.pool.Count; } } - public int Size { get { return this.pool.Count; } } + // Available objects + private readonly ConcurrentBag pool = new ConcurrentBag(); - /// - /// Our pool of objects - /// - ConcurrentBag pool = new ConcurrentBag(); - - private ConcurrentDictionary inuse = new ConcurrentDictionary(); + // Unavailable objects + private readonly ConcurrentDictionary inuse = new ConcurrentDictionary(); /// /// The generator for creating new objects. /// /// - Func objectFactory; - + private readonly Func objectFactory; + /// /// Internal constructor for our ObjectPool. /// diff --git a/Hazel/Udp/UdpConnection.KeepAlive.cs b/Hazel/Udp/UdpConnection.KeepAlive.cs index 121ae18..20d1fac 100644 --- a/Hazel/Udp/UdpConnection.KeepAlive.cs +++ b/Hazel/Udp/UdpConnection.KeepAlive.cs @@ -1,9 +1,6 @@ using System; using System.Collections.Concurrent; -using System.Collections.Generic; using System.Diagnostics; -using System.Linq; -using System.Text; using System.Threading; @@ -105,8 +102,9 @@ namespace Hazel.Udp // Pings are special, quasi-reliable packets. // We send them to trigger responses that validate our connection is alive - // They should never be the *cause* of a disconnect. - // Rather, the responses will reset our + // An unacked ping should never be the sole cause of a disconnect. + // Rather, the responses will reset our pingsSinceAck, enough unacked + // pings should cause a disconnect. void SendPing() { ushort id = (ushort)Interlocked.Increment(ref lastIDAllocated); @@ -156,6 +154,14 @@ namespace Hazel.Udp this.keepAliveTimer = null; timer.Dispose(); } + + foreach (var kvp in activePingPackets) + { + if (this.activePingPackets.TryRemove(kvp.Key, out var pkt)) + { + pkt.Recycle(); + } + } } } } \ No newline at end of file diff --git a/Hazel/Udp/UdpConnection.Reliable.cs b/Hazel/Udp/UdpConnection.Reliable.cs index a7e915e..b18c8c8 100644 --- a/Hazel/Udp/UdpConnection.Reliable.cs +++ b/Hazel/Udp/UdpConnection.Reliable.cs @@ -227,13 +227,11 @@ namespace Hazel.Udp /// The callback to make once the packet has been acknowledged. void AttachReliableID(byte[] buffer, int offset, int sendLength, Action ackCallback = null) { - //Find an ID not used yet. ushort id = (ushort)Interlocked.Increment(ref lastIDAllocated); buffer[offset] = (byte)(id >> 8); buffer[offset + 1] = (byte)id; - //Create packet object Packet packet = Packet.GetObject(); packet.Set( id, @@ -409,9 +407,8 @@ namespace Hazel.Udp //Get ID ushort id = (ushort)((bytes[1] << 8) + bytes[2]); - //Dispose of timer and remove from dictionary - Packet packet; - if (reliableDataPacketsSent.TryRemove(id, out packet)) + // Dispose of timer and remove from dictionary + if (reliableDataPacketsSent.TryRemove(id, out Packet packet)) { float rt = packet.Stopwatch.ElapsedMilliseconds; @@ -426,12 +423,13 @@ namespace Hazel.Udp else if (this.activePingPackets.TryRemove(id, out PingPacket pingPkt)) { float rt = pingPkt.Stopwatch.ElapsedMilliseconds; + + pingPkt.Recycle(); + lock (PingLock) { this.AveragePingMs = Math.Max(50, this.AveragePingMs * .7f + rt * .3f); } - - pingPkt.Recycle(); } Statistics.LogReliableReceive(0, bytes.Length); @@ -464,8 +462,7 @@ namespace Hazel.Udp { foreach (var kvp in reliableDataPacketsSent) { - Packet pkt; - if (this.reliableDataPacketsSent.TryRemove(kvp.Key, out pkt)) + if (this.reliableDataPacketsSent.TryRemove(kvp.Key, out var pkt)) { pkt.Recycle(); } diff --git a/Hazel/Udp/UdpConnection.cs b/Hazel/Udp/UdpConnection.cs index 503b1c6..051214e 100644 --- a/Hazel/Udp/UdpConnection.cs +++ b/Hazel/Udp/UdpConnection.cs @@ -34,7 +34,6 @@ namespace Hazel.Udp /// public override void Send(MessageWriter msg) { - //Early check if (this._state != ConnectionState.Connected) throw new InvalidOperationException("Could not send data as this Connection is not connected. Did you disconnect?"); diff --git a/Hazel/Udp/UdpConnectionListener.cs b/Hazel/Udp/UdpConnectionListener.cs index 9a8a3d9..e1d6f46 100644 --- a/Hazel/Udp/UdpConnectionListener.cs +++ b/Hazel/Udp/UdpConnectionListener.cs @@ -115,8 +115,6 @@ namespace Hazel.Udp } catch (SocketException) { - //Client no longer reachable, pretend it didn't happen - //TODO possibly able to disconnect client, see other TODO message?.Recycle(); StartListeningForData(); return; @@ -124,6 +122,7 @@ namespace Hazel.Udp catch (Exception ex) { //If the socket's been disposed then we can just end there. + message.Recycle(); this.Logger?.Invoke("Stopped due to: " + ex.Message); return; } @@ -169,6 +168,7 @@ namespace Hazel.Udp catch (Exception ex) { //If the socket's been disposed then we can just end there. + message.Recycle(); this.Logger?.Invoke("Stopped due to: " + ex.Message); return; } diff --git a/Hazel/Udp/UdpServerConnection.cs b/Hazel/Udp/UdpServerConnection.cs index 4c18a6e..fa15edb 100644 --- a/Hazel/Udp/UdpServerConnection.cs +++ b/Hazel/Udp/UdpServerConnection.cs @@ -85,8 +85,8 @@ namespace Hazel.Udp if (this._state == ConnectionState.Connected || this._state == ConnectionState.Disconnecting) { - SendDisconnect(); this._state = ConnectionState.NotConnected; + SendDisconnect(); } }