From 0b471f2b2f190c5b769573e92b56065c9ada78e1 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Wed, 18 Apr 2018 04:56:41 -0700 Subject: [PATCH] Sockets: do 0 byte reads to avoid allocating memory for idle connections - Do not do 0 byte reads on OSX due to potential sockets bug --- .../Internal/SocketConnection.cs | 8 ++++++++ .../Internal/SocketReceiver.cs | 12 ++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/Kestrel.Transport.Sockets/Internal/SocketConnection.cs b/src/Kestrel.Transport.Sockets/Internal/SocketConnection.cs index ec9a96e2f7..4cba0b3611 100644 --- a/src/Kestrel.Transport.Sockets/Internal/SocketConnection.cs +++ b/src/Kestrel.Transport.Sockets/Internal/SocketConnection.cs @@ -21,6 +21,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal { private static readonly int MinAllocBufferSize = KestrelMemoryPool.MinimumSegmentSize / 2; private static readonly bool IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + private static readonly bool IsMacOS = RuntimeInformation.IsOSPlatform(OSPlatform.OSX); private readonly Socket _socket; private readonly PipeScheduler _scheduler; @@ -164,6 +165,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal { while (true) { + // MacOS blocked on https://github.com/dotnet/corefx/issues/31766 + if (!IsMacOS) + { + // Wait for data before allocating a buffer. + await _receiver.WaitForDataAsync(); + } + // Ensure we have some reasonable amount of buffer space var buffer = Input.GetMemory(MinAllocBufferSize); diff --git a/src/Kestrel.Transport.Sockets/Internal/SocketReceiver.cs b/src/Kestrel.Transport.Sockets/Internal/SocketReceiver.cs index d84b1dfa9d..5d33f49829 100644 --- a/src/Kestrel.Transport.Sockets/Internal/SocketReceiver.cs +++ b/src/Kestrel.Transport.Sockets/Internal/SocketReceiver.cs @@ -13,6 +13,18 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal { } + public SocketAwaitableEventArgs WaitForDataAsync() + { + _awaitableEventArgs.SetBuffer(Array.Empty(), 0, 0); + + if (!_socket.ReceiveAsync(_awaitableEventArgs)) + { + _awaitableEventArgs.Complete(); + } + + return _awaitableEventArgs; + } + public SocketAwaitableEventArgs ReceiveAsync(Memory buffer) { #if NETCOREAPP2_1