Don't rely on the finalizer to return blocks referenced by SocketInput

This commit is contained in:
Stephen Halter 2016-01-26 17:35:35 -08:00
parent 87bd60746b
commit 9c31907bac
6 changed files with 50 additions and 12 deletions

View File

@ -48,10 +48,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Filter
{
if (copyAsyncTask.IsFaulted)
{
SocketInput.AbortAwaiting();
_log.LogError(0, copyAsyncTask.Exception, "FilteredStreamAdapter.CopyToAsync");
}
else if (copyAsyncTask.IsCanceled)
{
SocketInput.AbortAwaiting();
_log.LogError("FilteredStreamAdapter.CopyToAsync canceled.");
}

View File

@ -123,6 +123,18 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
}
}
public void OnSocketClosed()
{
_rawSocketInput.Dispose();
// If a connection filter was applied there will be two SocketInputs.
// If a connection filter failed, SocketInput will be null.
if (SocketInput != null && SocketInput != _rawSocketInput)
{
SocketInput.Dispose();
}
}
private void ApplyConnectionFilter()
{
if (_filterContext.Connection != _libuvStream)

View File

@ -334,7 +334,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
try
{
ConnectionControl.End(ProduceEndType.SocketDisconnect);
SocketInput.AbortAwaiting();
}
catch (Exception ex)
{

View File

@ -145,14 +145,20 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
// If _requestAborted is set, the connection has already been closed.
if (Volatile.Read(ref _requestAborted) == 0)
{
// Inform client no more data will ever arrive
ConnectionControl.End(ProduceEndType.SocketShutdownSend);
try
{
// Inform client no more data will ever arrive
ConnectionControl.End(ProduceEndType.SocketShutdownSend);
// Wait for client to either disconnect or send unexpected data
await SocketInput;
// Dispose socket
ConnectionControl.End(ProduceEndType.SocketDisconnect);
// Wait for client to either disconnect or send unexpected data
await SocketInput;
}
finally
{
// Ensure we *always* disconnect the socket.
// Dispose socket
ConnectionControl.End(ProduceEndType.SocketDisconnect);
}
}
}
catch (Exception ex)

View File

@ -10,7 +10,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Infrastructure;
namespace Microsoft.AspNetCore.Server.Kestrel.Http
{
public class SocketInput : ICriticalNotifyCompletion
public class SocketInput : ICriticalNotifyCompletion, IDisposable
{
private static readonly Action _awaitableIsCompleted = () => { };
private static readonly Action _awaitableIsNotCompleted = () => { };
@ -246,5 +246,23 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
throw new IOException(error.Message, error);
}
}
public void Dispose()
{
AbortAwaiting();
// Return all blocks
var block = _head;
while (block != null)
{
var returnBlock = block;
block = block.Next;
returnBlock.Pool.Return(returnBlock);
}
_head = null;
_tail = null;
}
}
}

View File

@ -614,17 +614,18 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
{
if (SocketDisconnect == false || Self._socket.IsClosed)
{
CompleteOnUvThread();
CompleteWithContextLock();
return;
}
Self._socket.Dispose();
Self._connection.OnSocketClosed();
Self.ReturnAllBlocks();
Self._log.ConnectionStop(Self._connectionId);
CompleteOnUvThread();
CompleteWithContextLock();
}
public void CompleteOnUvThread()
public void CompleteWithContextLock()
{
if (Monitor.TryEnter(Self._contextLock))
{