зеркало из https://github.com/dotnet/aspnetcore.git
Make the HTTP.sys accept loop cheaper (#28345)
* Make the HTTP.sys accept loop cheaper - Allocate a single AsyncAcceptContext per loop instead of one per request. - The AsyncAcceptContext now implements IValueTaskSource instead of Task and doesn't allocate a Task per request. - Use a preallocated overlapped since we don't have overlapping calls to accept for a single AsyncAcceptContext. - Remove some dead code from SafeNativeOverlapped * Clear the nativeRequestContext on dispose * PR feedback - Move NativeOverlapped* to the AsyncAcceptContext. This removes the SafeNativeOverlapped allocation as the lifetime is managed by the AsyncAcceptContext - Rename tcs * Send the error response before settings the result
This commit is contained in:
Родитель
ec2e8a0444
Коммит
5d4dac2f9f
|
@ -1,29 +1,29 @@
|
|||
{
|
||||
{
|
||||
"solution": {
|
||||
"path": "..\\..\\..\\AspNetCore.sln",
|
||||
"projects" : [
|
||||
"src\\Servers\\HttpSys\\samples\\TestClient\\TestClient.csproj",
|
||||
"src\\Servers\\HttpSys\\samples\\SelfHostServer\\SelfHostServer.csproj",
|
||||
"src\\Servers\\HttpSys\\samples\\HotAddSample\\HotAddSample.csproj",
|
||||
"src\\Servers\\HttpSys\\test\\FunctionalTests\\Microsoft.AspNetCore.Server.HttpSys.FunctionalTests.csproj",
|
||||
"src\\Servers\\HttpSys\\test\\Tests\\Microsoft.AspNetCore.Server.HttpSys.Tests.csproj",
|
||||
"src\\Servers\\HttpSys\\src\\Microsoft.AspNetCore.Server.HttpSys.csproj",
|
||||
"projects": [
|
||||
"src\\DefaultBuilder\\src\\Microsoft.AspNetCore.csproj",
|
||||
"src\\Hosting\\Abstractions\\src\\Microsoft.AspNetCore.Hosting.Abstractions.csproj",
|
||||
"src\\Hosting\\Hosting\\src\\Microsoft.AspNetCore.Hosting.csproj",
|
||||
"src\\Hosting\\Server.Abstractions\\src\\Microsoft.AspNetCore.Hosting.Server.Abstractions.csproj",
|
||||
"src\\Http\\Authentication.Abstractions\\src\\Microsoft.AspNetCore.Authentication.Abstractions.csproj",
|
||||
"src\\Http\\Authentication.Core\\src\\Microsoft.AspNetCore.Authentication.Core.csproj",
|
||||
"src\\Http\\Headers\\src\\Microsoft.Net.Http.Headers.csproj",
|
||||
"src\\Http\\Http\\src\\Microsoft.AspNetCore.Http.csproj",
|
||||
"src\\Http\\Http.Abstractions\\src\\Microsoft.AspNetCore.Http.Abstractions.csproj",
|
||||
"src\\Http\\Http.Extensions\\src\\Microsoft.AspNetCore.Http.Extensions.csproj",
|
||||
"src\\Http\\Http.Features\\src\\Microsoft.AspNetCore.Http.Features.csproj",
|
||||
"src\\Http\\Http\\src\\Microsoft.AspNetCore.Http.csproj",
|
||||
"src\\Http\\Metadata\\src\\Microsoft.AspNetCore.Metadata.csproj",
|
||||
"src\\Http\\WebUtilities\\src\\Microsoft.AspNetCore.WebUtilities.csproj",
|
||||
"src\\Hosting\\Abstractions\\src\\Microsoft.AspNetCore.Hosting.Abstractions.csproj",
|
||||
"src\\Hosting\\Hosting\\src\\Microsoft.AspNetCore.Hosting.csproj",
|
||||
"src\\Servers\\Connections.Abstractions\\src\\Microsoft.AspNetCore.Connections.Abstractions.csproj",
|
||||
"src\\Servers\\HttpSys\\samples\\HotAddSample\\HotAddSample.csproj",
|
||||
"src\\Servers\\HttpSys\\samples\\QueueSharing\\QueueSharing.csproj",
|
||||
"src\\Servers\\Kestrel\\Transport.Sockets\\src\\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.csproj",
|
||||
"src\\DefaultBuilder\\src\\Microsoft.AspNetCore.csproj"
|
||||
"src\\Servers\\HttpSys\\samples\\SelfHostServer\\SelfHostServer.csproj",
|
||||
"src\\Servers\\HttpSys\\samples\\TestClient\\TestClient.csproj",
|
||||
"src\\Servers\\HttpSys\\src\\Microsoft.AspNetCore.Server.HttpSys.csproj",
|
||||
"src\\Servers\\HttpSys\\test\\FunctionalTests\\Microsoft.AspNetCore.Server.HttpSys.FunctionalTests.csproj",
|
||||
"src\\Servers\\HttpSys\\test\\Tests\\Microsoft.AspNetCore.Server.HttpSys.Tests.csproj",
|
||||
"src\\Servers\\Kestrel\\Transport.Sockets\\src\\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.csproj"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,121 +2,135 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading.Tasks.Sources;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.HttpSys.Internal;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
||||
{
|
||||
internal unsafe class AsyncAcceptContext : TaskCompletionSource<RequestContext>, IDisposable
|
||||
internal unsafe class AsyncAcceptContext : IValueTaskSource<RequestContext>, IDisposable
|
||||
{
|
||||
internal static readonly IOCompletionCallback IOCallback = new IOCompletionCallback(IOWaitCallback);
|
||||
private static readonly IOCompletionCallback IOCallback = IOWaitCallback;
|
||||
private readonly PreAllocatedOverlapped _preallocatedOverlapped;
|
||||
private NativeOverlapped* _overlapped;
|
||||
|
||||
// mutable struct; do not make this readonly
|
||||
private ManualResetValueTaskSourceCore<RequestContext> _mrvts = new()
|
||||
{
|
||||
// We want to run continuations on the IO threads
|
||||
RunContinuationsAsynchronously = false
|
||||
};
|
||||
|
||||
private NativeRequestContext _nativeRequestContext;
|
||||
|
||||
internal AsyncAcceptContext(HttpSysListener server)
|
||||
{
|
||||
Server = server;
|
||||
AllocateNativeRequest();
|
||||
_preallocatedOverlapped = new(IOCallback, state: this, pinData: null);
|
||||
}
|
||||
|
||||
internal HttpSysListener Server { get; }
|
||||
|
||||
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Redirecting to callback")]
|
||||
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Disposed by callback")]
|
||||
internal ValueTask<RequestContext> AcceptAsync()
|
||||
{
|
||||
_mrvts.Reset();
|
||||
|
||||
AllocateNativeRequest();
|
||||
|
||||
uint statusCode = QueueBeginGetContext();
|
||||
if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS &&
|
||||
statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING)
|
||||
{
|
||||
// some other bad error, possible(?) return values are:
|
||||
// ERROR_INVALID_HANDLE, ERROR_INSUFFICIENT_BUFFER, ERROR_OPERATION_ABORTED
|
||||
return ValueTask.FromException<RequestContext>(new HttpSysException((int)statusCode));
|
||||
}
|
||||
|
||||
return new ValueTask<RequestContext>(this, _mrvts.Version);
|
||||
}
|
||||
|
||||
private static void IOCompleted(AsyncAcceptContext asyncContext, uint errorCode, uint numBytes)
|
||||
{
|
||||
bool complete = false;
|
||||
|
||||
try
|
||||
{
|
||||
if (errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS &&
|
||||
errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_MORE_DATA)
|
||||
{
|
||||
asyncContext.TrySetException(new HttpSysException((int)errorCode));
|
||||
complete = true;
|
||||
asyncContext._mrvts.SetException(new HttpSysException((int)errorCode));
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
HttpSysListener server = asyncContext.Server;
|
||||
if (errorCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS)
|
||||
{
|
||||
// at this point we have received an unmanaged HTTP_REQUEST and memoryBlob
|
||||
// points to it we need to hook up our authentication handling code here.
|
||||
try
|
||||
{
|
||||
if (server.ValidateRequest(asyncContext._nativeRequestContext) && server.ValidateAuth(asyncContext._nativeRequestContext))
|
||||
{
|
||||
RequestContext requestContext = new RequestContext(server, asyncContext._nativeRequestContext);
|
||||
asyncContext.TrySetResult(requestContext);
|
||||
complete = true;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
server.SendError(asyncContext._nativeRequestContext.RequestId, StatusCodes.Status400BadRequest);
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// The request has been handed to the user, which means this code can't reuse the blob. Reset it here.
|
||||
if (complete)
|
||||
{
|
||||
asyncContext._nativeRequestContext = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
asyncContext.AllocateNativeRequest(size: asyncContext._nativeRequestContext.Size);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// (uint)backingBuffer.Length - AlignmentPadding
|
||||
asyncContext.AllocateNativeRequest(numBytes, asyncContext._nativeRequestContext.RequestId);
|
||||
}
|
||||
|
||||
// We need to issue a new request, either because auth failed, or because our buffer was too small the first time.
|
||||
if (!complete)
|
||||
HttpSysListener server = asyncContext.Server;
|
||||
if (errorCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS)
|
||||
{
|
||||
// at this point we have received an unmanaged HTTP_REQUEST and memoryBlob
|
||||
// points to it we need to hook up our authentication handling code here.
|
||||
try
|
||||
{
|
||||
uint statusCode = asyncContext.QueueBeginGetContext();
|
||||
if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS &&
|
||||
statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING)
|
||||
var nativeContext = asyncContext._nativeRequestContext;
|
||||
|
||||
if (server.ValidateRequest(nativeContext) && server.ValidateAuth(nativeContext))
|
||||
{
|
||||
// someother bad error, possible(?) return values are:
|
||||
// ERROR_INVALID_HANDLE, ERROR_INSUFFICIENT_BUFFER, ERROR_OPERATION_ABORTED
|
||||
asyncContext.TrySetException(new HttpSysException((int)statusCode));
|
||||
// It's important that we clear the native request context before we set the result
|
||||
// we want to reuse this object for future accepts.
|
||||
asyncContext._nativeRequestContext = null;
|
||||
|
||||
var requestContext = new RequestContext(server, nativeContext);
|
||||
asyncContext._mrvts.SetResult(requestContext);
|
||||
|
||||
complete = true;
|
||||
}
|
||||
}
|
||||
if (!complete)
|
||||
catch (Exception ex)
|
||||
{
|
||||
return;
|
||||
server.SendError(asyncContext._nativeRequestContext.RequestId, StatusCodes.Status400BadRequest);
|
||||
asyncContext._mrvts.SetException(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (!complete)
|
||||
{
|
||||
asyncContext.AllocateNativeRequest(size: asyncContext._nativeRequestContext.Size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (complete)
|
||||
else
|
||||
{
|
||||
asyncContext.Dispose();
|
||||
// (uint)backingBuffer.Length - AlignmentPadding
|
||||
asyncContext.AllocateNativeRequest(numBytes, asyncContext._nativeRequestContext.RequestId);
|
||||
}
|
||||
|
||||
// We need to issue a new request, either because auth failed, or because our buffer was too small the first time.
|
||||
if (!complete)
|
||||
{
|
||||
uint statusCode = asyncContext.QueueBeginGetContext();
|
||||
|
||||
if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS &&
|
||||
statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING)
|
||||
{
|
||||
// someother bad error, possible(?) return values are:
|
||||
// ERROR_INVALID_HANDLE, ERROR_INSUFFICIENT_BUFFER, ERROR_OPERATION_ABORTED
|
||||
asyncContext._mrvts.SetException(new HttpSysException((int)statusCode));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
// Logged by caller
|
||||
asyncContext.TrySetException(exception);
|
||||
asyncContext.Dispose();
|
||||
asyncContext._mrvts.SetException(exception);
|
||||
}
|
||||
}
|
||||
|
||||
private static unsafe void IOWaitCallback(uint errorCode, uint numBytes, NativeOverlapped* nativeOverlapped)
|
||||
{
|
||||
// take the ListenerAsyncResult object from the state
|
||||
var asyncResult = (AsyncAcceptContext)ThreadPoolBoundHandle.GetNativeOverlappedState(nativeOverlapped);
|
||||
IOCompleted(asyncResult, errorCode, numBytes);
|
||||
}
|
||||
|
||||
internal uint QueueBeginGetContext()
|
||||
private uint QueueBeginGetContext()
|
||||
{
|
||||
uint statusCode = UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS;
|
||||
bool retry;
|
||||
|
@ -133,7 +147,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
_nativeRequestContext.NativeRequest,
|
||||
_nativeRequestContext.Size,
|
||||
&bytesTransferred,
|
||||
_nativeRequestContext.NativeOverlapped);
|
||||
_overlapped);
|
||||
|
||||
if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_INVALID_PARAMETER && _nativeRequestContext.RequestId != 0)
|
||||
{
|
||||
|
@ -162,18 +176,20 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
return statusCode;
|
||||
}
|
||||
|
||||
internal void AllocateNativeRequest(uint? size = null, ulong requestId = 0)
|
||||
private void AllocateNativeRequest(uint? size = null, ulong requestId = 0)
|
||||
{
|
||||
_nativeRequestContext?.ReleasePins();
|
||||
_nativeRequestContext?.Dispose();
|
||||
|
||||
// We can't reuse overlapped objects
|
||||
var boundHandle = Server.RequestQueue.BoundHandle;
|
||||
var nativeOverlapped = new SafeNativeOverlapped(boundHandle,
|
||||
boundHandle.AllocateNativeOverlapped(IOCallback, this, pinData: null));
|
||||
|
||||
// nativeRequest
|
||||
_nativeRequestContext = new NativeRequestContext(nativeOverlapped, Server.MemoryPool, size, requestId);
|
||||
if (_overlapped != null)
|
||||
{
|
||||
boundHandle.FreeNativeOverlapped(_overlapped);
|
||||
}
|
||||
|
||||
_nativeRequestContext = new NativeRequestContext(Server.MemoryPool, size, requestId);
|
||||
_overlapped = boundHandle.AllocateNativeOverlapped(_preallocatedOverlapped);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
@ -189,8 +205,32 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
{
|
||||
_nativeRequestContext.ReleasePins();
|
||||
_nativeRequestContext.Dispose();
|
||||
_nativeRequestContext = null;
|
||||
|
||||
var boundHandle = Server.RequestQueue.BoundHandle;
|
||||
|
||||
if (_overlapped != null)
|
||||
{
|
||||
boundHandle.FreeNativeOverlapped(_overlapped);
|
||||
_overlapped = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public RequestContext GetResult(short token)
|
||||
{
|
||||
return _mrvts.GetResult(token);
|
||||
}
|
||||
|
||||
public ValueTaskSourceStatus GetStatus(short token)
|
||||
{
|
||||
return _mrvts.GetStatus(token);
|
||||
}
|
||||
|
||||
public void OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags)
|
||||
{
|
||||
_mrvts.OnCompleted(continuation, state, token, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -195,7 +195,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
return;
|
||||
}
|
||||
|
||||
Logger.LogTrace(LoggerEventIds.ListenerStopping,"Stopping the listener.");
|
||||
Logger.LogTrace(LoggerEventIds.ListenerStopping, "Stopping the listener.");
|
||||
|
||||
// If this instance created the queue then remove the URL prefixes before shutting down.
|
||||
if (_requestQueue.Created)
|
||||
|
@ -277,34 +277,12 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
/// <summary>
|
||||
/// Accept a request from the incoming request queue.
|
||||
/// </summary>
|
||||
public Task<RequestContext> AcceptAsync()
|
||||
internal ValueTask<RequestContext> AcceptAsync(AsyncAcceptContext acceptContext)
|
||||
{
|
||||
AsyncAcceptContext acceptContext = null;
|
||||
try
|
||||
{
|
||||
CheckDisposed();
|
||||
Debug.Assert(_state != State.Stopped, "Listener has been stopped.");
|
||||
// prepare the ListenerAsyncResult object (this will have it's own
|
||||
// event that the user can wait on for IO completion - which means we
|
||||
// need to signal it when IO completes)
|
||||
acceptContext = new AsyncAcceptContext(this);
|
||||
uint statusCode = acceptContext.QueueBeginGetContext();
|
||||
if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS &&
|
||||
statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING)
|
||||
{
|
||||
// some other bad error, possible(?) return values are:
|
||||
// ERROR_INVALID_HANDLE, ERROR_INSUFFICIENT_BUFFER, ERROR_OPERATION_ABORTED
|
||||
acceptContext.Dispose();
|
||||
throw new HttpSysException((int)statusCode);
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Logger.LogError(LoggerEventIds.AcceptError, exception, "AcceptAsync");
|
||||
throw;
|
||||
}
|
||||
CheckDisposed();
|
||||
Debug.Assert(_state != State.Stopped, "Listener has been stopped.");
|
||||
|
||||
return acceptContext.Task;
|
||||
return acceptContext.AcceptAsync();
|
||||
}
|
||||
|
||||
internal unsafe bool ValidateRequest(NativeRequestContext requestMemory)
|
||||
|
|
|
@ -178,6 +178,9 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
// The awaits will manage stack depth for us.
|
||||
private async Task ProcessRequestsWorker()
|
||||
{
|
||||
// Allocate and accept context per loop and reuse it for all accepts
|
||||
using var acceptContext = new AsyncAcceptContext(Listener);
|
||||
|
||||
int workerIndex = Interlocked.Increment(ref _acceptorCounts);
|
||||
while (!Stopping && workerIndex <= _maxAccepts)
|
||||
{
|
||||
|
@ -185,7 +188,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
RequestContext requestContext;
|
||||
try
|
||||
{
|
||||
requestContext = await Listener.AcceptAsync();
|
||||
requestContext = await Listener.AcceptAsync(acceptContext);
|
||||
// Assign the message pump to this request context
|
||||
requestContext.MessagePump = this;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using Microsoft.AspNetCore.HttpSys.Internal;
|
||||
using static Microsoft.AspNetCore.HttpSys.Internal.HttpApiTypes;
|
||||
|
||||
|
@ -25,7 +26,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
internal static extern uint HttpReceiveClientCertificate(SafeHandle requestQueueHandle, ulong connectionId, uint flags, byte* pSslClientCertInfo, uint sslClientCertInfoSize, uint* pBytesReceived, SafeNativeOverlapped pOverlapped);
|
||||
|
||||
[DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
|
||||
internal static extern uint HttpReceiveHttpRequest(SafeHandle requestQueueHandle, ulong requestId, uint flags, HTTP_REQUEST* pRequestBuffer, uint requestBufferLength, uint* pBytesReturned, SafeNativeOverlapped pOverlapped);
|
||||
internal static extern uint HttpReceiveHttpRequest(SafeHandle requestQueueHandle, ulong requestId, uint flags, HTTP_REQUEST* pRequestBuffer, uint requestBufferLength, uint* pBytesReturned, NativeOverlapped* pOverlapped);
|
||||
|
||||
[DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
|
||||
internal static extern uint HttpSendHttpResponse(SafeHandle requestQueueHandle, ulong requestId, uint flags, HTTP_RESPONSE_V2* pHttpResponse, HTTP_CACHE_POLICY* pCachePolicy, uint* pBytesSent, IntPtr pReserved1, uint Reserved2, SafeNativeOverlapped pOverlapped, IntPtr pLogData);
|
||||
|
|
|
@ -113,7 +113,8 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
/// </summary>
|
||||
internal static async Task<RequestContext> AcceptAsync(this HttpSysListener server, TimeSpan timeout)
|
||||
{
|
||||
var acceptTask = server.AcceptAsync();
|
||||
var acceptContext = new AsyncAcceptContext(server);
|
||||
var acceptTask = server.AcceptAsync(acceptContext).AsTask();
|
||||
var completedTask = await Task.WhenAny(acceptTask, Task.Delay(timeout));
|
||||
|
||||
if (completedTask == acceptTask)
|
||||
|
|
|
@ -29,21 +29,6 @@ namespace Microsoft.AspNetCore.HttpSys.Internal
|
|||
get { return handle == IntPtr.Zero; }
|
||||
}
|
||||
|
||||
public void ReinitializeNativeOverlapped()
|
||||
{
|
||||
IntPtr handleSnapshot = handle;
|
||||
|
||||
if (handleSnapshot != IntPtr.Zero)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
((NativeOverlapped*)handleSnapshot)->InternalHigh = IntPtr.Zero;
|
||||
((NativeOverlapped*)handleSnapshot)->InternalLow = IntPtr.Zero;
|
||||
((NativeOverlapped*)handleSnapshot)->EventHandle = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool ReleaseHandle()
|
||||
{
|
||||
IntPtr oldHandle = Interlocked.Exchange(ref handle, IntPtr.Zero);
|
||||
|
|
|
@ -25,15 +25,12 @@ namespace Microsoft.AspNetCore.HttpSys.Internal
|
|||
private IMemoryOwner<byte> _backingBuffer;
|
||||
private MemoryHandle _memoryHandle;
|
||||
private int _bufferAlignment;
|
||||
private SafeNativeOverlapped _nativeOverlapped;
|
||||
private bool _permanentlyPinned;
|
||||
private bool _disposed;
|
||||
|
||||
// To be used by HttpSys
|
||||
internal NativeRequestContext(SafeNativeOverlapped nativeOverlapped, MemoryPool<Byte> memoryPool, uint? bufferSize, ulong requestId)
|
||||
internal NativeRequestContext(MemoryPool<byte> memoryPool, uint? bufferSize, ulong requestId)
|
||||
{
|
||||
_nativeOverlapped = nativeOverlapped;
|
||||
|
||||
// TODO:
|
||||
// Apparently the HttpReceiveHttpRequest memory alignment requirements for non - ARM processors
|
||||
// are different than for ARM processors. We have seen 4 - byte - aligned buffers allocated on
|
||||
|
@ -70,8 +67,6 @@ namespace Microsoft.AspNetCore.HttpSys.Internal
|
|||
_permanentlyPinned = true;
|
||||
}
|
||||
|
||||
internal SafeNativeOverlapped NativeOverlapped => _nativeOverlapped;
|
||||
|
||||
internal HttpApiTypes.HTTP_REQUEST* NativeRequest
|
||||
{
|
||||
get
|
||||
|
@ -130,8 +125,6 @@ namespace Microsoft.AspNetCore.HttpSys.Internal
|
|||
_memoryHandle.Dispose();
|
||||
_memoryHandle = default;
|
||||
_nativeRequest = null;
|
||||
_nativeOverlapped?.Dispose();
|
||||
_nativeOverlapped = null;
|
||||
}
|
||||
|
||||
public virtual void Dispose()
|
||||
|
@ -140,7 +133,6 @@ namespace Microsoft.AspNetCore.HttpSys.Internal
|
|||
{
|
||||
_disposed = true;
|
||||
Debug.Assert(_nativeRequest == null, "RequestContextBase::Dispose()|Dispose() called before ReleasePins().");
|
||||
_nativeOverlapped?.Dispose();
|
||||
_memoryHandle.Dispose();
|
||||
_backingBuffer.Dispose();
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче