Don't rely on the finalizer to return blocks referenced by SocketInput
This commit is contained in:
parent
87bd60746b
commit
9c31907bac
|
|
@ -48,10 +48,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Filter
|
||||||
{
|
{
|
||||||
if (copyAsyncTask.IsFaulted)
|
if (copyAsyncTask.IsFaulted)
|
||||||
{
|
{
|
||||||
|
SocketInput.AbortAwaiting();
|
||||||
_log.LogError(0, copyAsyncTask.Exception, "FilteredStreamAdapter.CopyToAsync");
|
_log.LogError(0, copyAsyncTask.Exception, "FilteredStreamAdapter.CopyToAsync");
|
||||||
}
|
}
|
||||||
else if (copyAsyncTask.IsCanceled)
|
else if (copyAsyncTask.IsCanceled)
|
||||||
{
|
{
|
||||||
|
SocketInput.AbortAwaiting();
|
||||||
_log.LogError("FilteredStreamAdapter.CopyToAsync canceled.");
|
_log.LogError("FilteredStreamAdapter.CopyToAsync canceled.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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()
|
private void ApplyConnectionFilter()
|
||||||
{
|
{
|
||||||
if (_filterContext.Connection != _libuvStream)
|
if (_filterContext.Connection != _libuvStream)
|
||||||
|
|
|
||||||
|
|
@ -334,7 +334,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ConnectionControl.End(ProduceEndType.SocketDisconnect);
|
ConnectionControl.End(ProduceEndType.SocketDisconnect);
|
||||||
SocketInput.AbortAwaiting();
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -145,14 +145,20 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
|
||||||
// If _requestAborted is set, the connection has already been closed.
|
// If _requestAborted is set, the connection has already been closed.
|
||||||
if (Volatile.Read(ref _requestAborted) == 0)
|
if (Volatile.Read(ref _requestAborted) == 0)
|
||||||
{
|
{
|
||||||
// Inform client no more data will ever arrive
|
try
|
||||||
ConnectionControl.End(ProduceEndType.SocketShutdownSend);
|
{
|
||||||
|
// Inform client no more data will ever arrive
|
||||||
|
ConnectionControl.End(ProduceEndType.SocketShutdownSend);
|
||||||
|
|
||||||
// Wait for client to either disconnect or send unexpected data
|
// Wait for client to either disconnect or send unexpected data
|
||||||
await SocketInput;
|
await SocketInput;
|
||||||
|
}
|
||||||
// Dispose socket
|
finally
|
||||||
ConnectionControl.End(ProduceEndType.SocketDisconnect);
|
{
|
||||||
|
// Ensure we *always* disconnect the socket.
|
||||||
|
// Dispose socket
|
||||||
|
ConnectionControl.End(ProduceEndType.SocketDisconnect);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Infrastructure;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Http
|
namespace Microsoft.AspNetCore.Server.Kestrel.Http
|
||||||
{
|
{
|
||||||
public class SocketInput : ICriticalNotifyCompletion
|
public class SocketInput : ICriticalNotifyCompletion, IDisposable
|
||||||
{
|
{
|
||||||
private static readonly Action _awaitableIsCompleted = () => { };
|
private static readonly Action _awaitableIsCompleted = () => { };
|
||||||
private static readonly Action _awaitableIsNotCompleted = () => { };
|
private static readonly Action _awaitableIsNotCompleted = () => { };
|
||||||
|
|
@ -246,5 +246,23 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
|
||||||
throw new IOException(error.Message, error);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -614,17 +614,18 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
|
||||||
{
|
{
|
||||||
if (SocketDisconnect == false || Self._socket.IsClosed)
|
if (SocketDisconnect == false || Self._socket.IsClosed)
|
||||||
{
|
{
|
||||||
CompleteOnUvThread();
|
CompleteWithContextLock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Self._socket.Dispose();
|
Self._socket.Dispose();
|
||||||
|
Self._connection.OnSocketClosed();
|
||||||
Self.ReturnAllBlocks();
|
Self.ReturnAllBlocks();
|
||||||
Self._log.ConnectionStop(Self._connectionId);
|
Self._log.ConnectionStop(Self._connectionId);
|
||||||
CompleteOnUvThread();
|
CompleteWithContextLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CompleteOnUvThread()
|
public void CompleteWithContextLock()
|
||||||
{
|
{
|
||||||
if (Monitor.TryEnter(Self._contextLock))
|
if (Monitor.TryEnter(Self._contextLock))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue