Merge branch 'release' into dev

This commit is contained in:
Chris R 2015-06-04 10:18:31 -07:00
Родитель c958d01112 532698abd3
Коммит 0acb8f3ed4
16 изменённых файлов: 385 добавлений и 145 удалений

Просмотреть файл

@ -60,7 +60,7 @@ namespace Microsoft.Net.Http.Server
}
}
private WebListener Server
internal WebListener Server
{
get
{
@ -152,9 +152,7 @@ namespace Microsoft.Net.Http.Server
private static unsafe void IOWaitCallback(uint errorCode, uint numBytes, NativeOverlapped* nativeOverlapped)
{
// take the ListenerAsyncResult object from the state
Overlapped callbackOverlapped = Overlapped.Unpack(nativeOverlapped);
AsyncAcceptContext asyncResult = (AsyncAcceptContext)callbackOverlapped.AsyncResult;
var asyncResult = (AsyncAcceptContext)ThreadPoolBoundHandle.GetNativeOverlappedState(nativeOverlapped);
IOCompleted(asyncResult, errorCode, numBytes);
}

Просмотреть файл

@ -30,21 +30,18 @@ namespace Microsoft.Net.Http.Server
internal class SafeNativeOverlapped : SafeHandle
{
internal static readonly SafeNativeOverlapped Zero = new SafeNativeOverlapped();
private ThreadPoolBoundHandle _boundHandle;
internal SafeNativeOverlapped()
: this(IntPtr.Zero)
{
}
internal unsafe SafeNativeOverlapped(NativeOverlapped* handle)
: this((IntPtr)handle)
{
}
internal SafeNativeOverlapped(IntPtr handle)
: base(IntPtr.Zero, true)
{
SetHandle(handle);
}
internal unsafe SafeNativeOverlapped(ThreadPoolBoundHandle boundHandle, NativeOverlapped* handle)
: base(IntPtr.Zero, true)
{
SetHandle((IntPtr)handle);
_boundHandle = boundHandle;
}
public override bool IsInvalid
@ -76,7 +73,7 @@ namespace Microsoft.Net.Http.Server
{
unsafe
{
Overlapped.Free((NativeOverlapped*)oldHandle);
_boundHandle.FreeNativeOverlapped((NativeOverlapped*)oldHandle);
}
}
return true;

Просмотреть файл

@ -0,0 +1,85 @@
#if !DNXCORE50 // TODO: Temp copy. Remove once we target net46.
using System;
namespace System.Threading
{
internal struct DeferredDisposableLifetime<T> where T : class, IDeferredDisposable
{
private int _count;
public bool AddRef(T obj)
{
while (true)
{
int num = Volatile.Read(ref this._count);
if (num < 0)
{
break;
}
int num2 = checked(num + 1);
if (Interlocked.CompareExchange(ref this._count, num2, num) == num)
{
return true;
}
}
throw new ObjectDisposedException(typeof(T).ToString());
}
public void Release(T obj)
{
int num2;
int num3;
while (true)
{
int num = Volatile.Read(ref this._count);
if (num > 0)
{
num2 = num - 1;
if (Interlocked.CompareExchange(ref this._count, num2, num) == num)
{
break;
}
}
else
{
num3 = num + 1;
if (Interlocked.CompareExchange(ref this._count, num3, num) == num)
{
goto Block_3;
}
}
}
if (num2 == 0)
{
obj.OnFinalRelease(false);
}
return;
Block_3:
if (num3 == -1)
{
obj.OnFinalRelease(true);
}
}
public void Dispose(T obj)
{
int num2;
while (true)
{
int num = Volatile.Read(ref this._count);
if (num < 0)
{
break;
}
num2 = -1 - num;
if (Interlocked.CompareExchange(ref this._count, num2, num) == num)
{
goto Block_1;
}
}
return;
Block_1:
if (num2 == -1)
{
obj.OnFinalRelease(true);
}
}
}
}
#endif

Просмотреть файл

@ -0,0 +1,10 @@
#if !DNXCORE50 // TODO: Temp copy. Remove once we target net46.
using System;
namespace System.Threading
{
internal interface IDeferredDisposable
{
void OnFinalRelease(bool disposed);
}
}
#endif

Просмотреть файл

@ -0,0 +1,51 @@
#if !DNXCORE50 // TODO: Temp copy. Remove once we target net46.
using System;
namespace System.Threading
{
public sealed class PreAllocatedOverlapped : IDisposable, IDeferredDisposable
{
internal readonly ThreadPoolBoundHandleOverlapped _overlapped;
private DeferredDisposableLifetime<PreAllocatedOverlapped> _lifetime;
[CLSCompliant(false)]
public PreAllocatedOverlapped(IOCompletionCallback callback, object state, object pinData)
{
if (callback == null)
{
throw new ArgumentNullException("callback");
}
this._overlapped = new ThreadPoolBoundHandleOverlapped(callback, state, pinData, this);
}
internal bool AddRef()
{
return this._lifetime.AddRef(this);
}
internal void Release()
{
this._lifetime.Release(this);
}
public void Dispose()
{
this._lifetime.Dispose(this);
GC.SuppressFinalize(this);
}
~PreAllocatedOverlapped()
{
if (!Environment.HasShutdownStarted)
{
this.Dispose();
}
}
unsafe void IDeferredDisposable.OnFinalRelease(bool disposed)
{
if (disposed)
{
Overlapped.Free(this._overlapped._nativeOverlapped);
return;
}
this._overlapped._boundHandle = null;
this._overlapped._completed = false;
*this._overlapped._nativeOverlapped = default(NativeOverlapped);
}
}
}
#endif

Просмотреть файл

@ -0,0 +1,143 @@
#if !DNXCORE50 // TODO: Temp copy. Remove once we target net46.
using System;
using System.Runtime.InteropServices;
namespace System.Threading
{
public sealed class ThreadPoolBoundHandle : IDisposable
{
private readonly SafeHandle _handle;
private bool _isDisposed;
public SafeHandle Handle
{
get
{
return this._handle;
}
}
private ThreadPoolBoundHandle(SafeHandle handle)
{
this._handle = handle;
}
public static ThreadPoolBoundHandle BindHandle(SafeHandle handle)
{
if (handle == null)
{
throw new ArgumentNullException("handle");
}
if (handle.IsClosed || handle.IsInvalid)
{
throw new ArgumentException("Invalid Handle", "handle");
}
try
{
ThreadPool.BindHandle(handle);
}
catch (Exception expr_38)
{
if (expr_38.HResult == -2147024890)
{
throw new ArgumentException("Invalid Handle", "handle");
}
if (expr_38.HResult == -2147024809)
{
throw new ArgumentException("Already Bound", "handle");
}
throw;
}
return new ThreadPoolBoundHandle(handle);
}
[CLSCompliant(false)]
public unsafe NativeOverlapped* AllocateNativeOverlapped(IOCompletionCallback callback, object state, object pinData)
{
if (callback == null)
{
throw new ArgumentNullException("callback");
}
this.EnsureNotDisposed();
return new ThreadPoolBoundHandleOverlapped(callback, state, pinData, null)
{
_boundHandle = this
}._nativeOverlapped;
}
[CLSCompliant(false)]
public unsafe NativeOverlapped* AllocateNativeOverlapped(PreAllocatedOverlapped preAllocated)
{
if (preAllocated == null)
{
throw new ArgumentNullException("preAllocated");
}
this.EnsureNotDisposed();
preAllocated.AddRef();
NativeOverlapped* nativeOverlapped;
try
{
ThreadPoolBoundHandleOverlapped expr_21 = preAllocated._overlapped;
if (expr_21._boundHandle != null)
{
throw new ArgumentException("Already Allocated", "preAllocated");
}
expr_21._boundHandle = this;
nativeOverlapped = expr_21._nativeOverlapped;
}
catch
{
preAllocated.Release();
throw;
}
return nativeOverlapped;
}
[CLSCompliant(false)]
public unsafe void FreeNativeOverlapped(NativeOverlapped* overlapped)
{
if (overlapped == null)
{
throw new ArgumentNullException("overlapped");
}
ThreadPoolBoundHandleOverlapped overlappedWrapper = ThreadPoolBoundHandle.GetOverlappedWrapper(overlapped, this);
if (overlappedWrapper._boundHandle != this)
{
throw new ArgumentException("Wrong bound handle", "overlapped");
}
if (overlappedWrapper._preAllocated != null)
{
overlappedWrapper._preAllocated.Release();
return;
}
Overlapped.Free(overlapped);
}
[CLSCompliant(false)]
public unsafe static object GetNativeOverlappedState(NativeOverlapped* overlapped)
{
if (overlapped == null)
{
throw new ArgumentNullException("overlapped");
}
return ThreadPoolBoundHandle.GetOverlappedWrapper(overlapped, null)._userState;
}
private unsafe static ThreadPoolBoundHandleOverlapped GetOverlappedWrapper(NativeOverlapped* overlapped, ThreadPoolBoundHandle expectedBoundHandle)
{
ThreadPoolBoundHandleOverlapped result;
try
{
result = (ThreadPoolBoundHandleOverlapped)Overlapped.Unpack(overlapped);
}
catch (NullReferenceException ex)
{
throw new ArgumentException("Already freed", "overlapped", ex);
}
return result;
}
public void Dispose()
{
this._isDisposed = true;
}
private void EnsureNotDisposed()
{
if (this._isDisposed)
{
throw new ObjectDisposedException(base.GetType().ToString());
}
}
}
}
#endif

Просмотреть файл

@ -0,0 +1,38 @@
#if !DNXCORE50 // TODO: Temp copy. Remove once we target net46.
using System;
namespace System.Threading
{
internal sealed class ThreadPoolBoundHandleOverlapped : Overlapped
{
private readonly IOCompletionCallback _userCallback;
internal readonly object _userState;
internal PreAllocatedOverlapped _preAllocated;
internal unsafe NativeOverlapped* _nativeOverlapped;
internal ThreadPoolBoundHandle _boundHandle;
internal bool _completed;
public unsafe ThreadPoolBoundHandleOverlapped(IOCompletionCallback callback, object state, object pinData, PreAllocatedOverlapped preAllocated)
{
this._userCallback = callback;
this._userState = state;
this._preAllocated = preAllocated;
this._nativeOverlapped = base.Pack(new IOCompletionCallback(ThreadPoolBoundHandleOverlapped.CompletionCallback), pinData);
this._nativeOverlapped->OffsetLow = 0;
this._nativeOverlapped->OffsetHigh = 0;
}
private unsafe static void CompletionCallback(uint errorCode, uint numBytes, NativeOverlapped* nativeOverlapped)
{
ThreadPoolBoundHandleOverlapped expr_0B = (ThreadPoolBoundHandleOverlapped)Overlapped.Unpack(nativeOverlapped);
if (expr_0B._completed)
{
throw new InvalidOperationException("Native Overlapped reused");
}
expr_0B._completed = true;
if (expr_0B._boundHandle == null)
{
throw new InvalidOperationException("Already freed");
}
expr_0B._userCallback.Invoke(errorCode, numBytes, nativeOverlapped);
}
}
}
#endif

Просмотреть файл

@ -138,9 +138,9 @@ namespace Microsoft.Net.Http.Server
return;
}
_backingBuffer = new byte[checked((int)size)];
Overlapped overlapped = new Overlapped();
overlapped.AsyncResult = this;
_overlapped = new SafeNativeOverlapped(overlapped.Pack(IOCallback, _backingBuffer));
var boundHandle = RequestContext.Server.BoundHandle;
_overlapped = new SafeNativeOverlapped(boundHandle,
boundHandle.AllocateNativeOverlapped(IOCallback, this, _backingBuffer));
_memoryBlob = (UnsafeNclNativeMethods.HttpApi.HTTP_SSL_CLIENT_CERT_INFO*)Marshal.UnsafeAddrOfPinnedArrayElement(_backingBuffer, 0);
}
@ -315,9 +315,7 @@ namespace Microsoft.Net.Http.Server
private static unsafe void WaitCallback(uint errorCode, uint numBytes, NativeOverlapped* nativeOverlapped)
{
Overlapped callbackOverlapped = Overlapped.Unpack(nativeOverlapped);
ClientCertLoader asyncResult = (ClientCertLoader)callbackOverlapped.AsyncResult;
var asyncResult = (ClientCertLoader)ThreadPoolBoundHandle.GetNativeOverlappedState(nativeOverlapped);
IOCompleted(asyncResult, errorCode, numBytes);
}

Просмотреть файл

@ -161,7 +161,8 @@ namespace Microsoft.Net.Http.Server
private UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST* Allocate(uint size)
{
uint newSize = size != 0 ? size : RequestBuffer == null ? DefaultBufferSize : Size;
if (_nativeOverlapped != null && newSize != RequestBuffer.Length)
// We can't reuse overlapped objects
if (_nativeOverlapped != null)
{
SafeNativeOverlapped nativeOverlapped = _nativeOverlapped;
_nativeOverlapped = null;
@ -170,9 +171,9 @@ namespace Microsoft.Net.Http.Server
if (_nativeOverlapped == null)
{
SetBuffer(checked((int)newSize));
Overlapped overlapped = new Overlapped();
overlapped.AsyncResult = _acceptResult;
_nativeOverlapped = new SafeNativeOverlapped(overlapped.Pack(AsyncAcceptContext.IOCallback, RequestBuffer));
var boundHandle = _acceptResult.Server.BoundHandle;
_nativeOverlapped = new SafeNativeOverlapped(boundHandle,
boundHandle.AllocateNativeOverlapped(AsyncAcceptContext.IOCallback, _acceptResult, RequestBuffer));
return (UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST*)Marshal.UnsafeAddrOfPinnedArrayElement(RequestBuffer, 0);
}
return RequestBlob;

Просмотреть файл

@ -43,6 +43,11 @@ namespace Microsoft.Net.Http.Server
_requestContext = httpContext;
}
internal RequestContext RequestContext
{
get { return _requestContext; }
}
public override bool CanSeek
{
get

Просмотреть файл

@ -64,9 +64,9 @@ namespace Microsoft.Net.Http.Server
: this(requestStream, userState, callback)
{
_dataAlreadyRead = dataAlreadyRead;
Overlapped overlapped = new Overlapped();
overlapped.AsyncResult = this;
_overlapped = new SafeNativeOverlapped(overlapped.Pack(IOCallback, buffer));
var boundHandle = requestStream.RequestContext.Server.BoundHandle;
_overlapped = new SafeNativeOverlapped(boundHandle,
boundHandle.AllocateNativeOverlapped(IOCallback, this, buffer));
_pinnedBuffer = (Marshal.UnsafeAddrOfPinnedArrayElement(buffer, offset));
_cancellationRegistration = cancellationRegistration;
}
@ -126,9 +126,7 @@ namespace Microsoft.Net.Http.Server
private static unsafe void Callback(uint errorCode, uint numBytes, NativeOverlapped* nativeOverlapped)
{
Overlapped callbackOverlapped = Overlapped.Unpack(nativeOverlapped);
RequestStreamAsyncResult asyncResult = callbackOverlapped.AsyncResult as RequestStreamAsyncResult;
var asyncResult = (RequestStreamAsyncResult)ThreadPoolBoundHandle.GetNativeOverlappedState(nativeOverlapped);
IOCompleted(asyncResult, errorCode, numBytes);
}

Просмотреть файл

@ -47,6 +47,11 @@ namespace Microsoft.Net.Http.Server
_requestContext = requestContext;
}
internal RequestContext RequestContext
{
get { return _requestContext; }
}
public override bool CanSeek
{
get

Просмотреть файл

@ -65,13 +65,13 @@ namespace Microsoft.Net.Http.Server
{
_sentHeaders = sentHeaders;
_cancellationRegistration = cancellationRegistration;
Overlapped overlapped = new Overlapped();
overlapped.AsyncResult = this;
var boundHandle = _responseStream.RequestContext.Server.BoundHandle;
if (size == 0)
{
_dataChunks = null;
_overlapped = new SafeNativeOverlapped(overlapped.Pack(IOCallback, null));
_overlapped = new SafeNativeOverlapped(boundHandle,
boundHandle.AllocateNativeOverlapped(IOCallback, this, null));
}
else
{
@ -114,7 +114,8 @@ namespace Microsoft.Net.Http.Server
}
// This call will pin needed memory
_overlapped = new SafeNativeOverlapped(overlapped.Pack(IOCallback, objectsToPin));
_overlapped = new SafeNativeOverlapped(boundHandle,
boundHandle.AllocateNativeOverlapped(IOCallback, this, objectsToPin));
if (chunked)
{
@ -136,8 +137,7 @@ namespace Microsoft.Net.Http.Server
{
_sentHeaders = sentHeaders;
_cancellationRegistration = cancellationRegistration;
Overlapped overlapped = new Overlapped();
overlapped.AsyncResult = this;
var boundHandle = ResponseStream.RequestContext.Server.BoundHandle;
int bufferSize = 1024 * 64; // TODO: Validate buffer size choice.
#if DNXCORE50
@ -162,7 +162,8 @@ namespace Microsoft.Net.Http.Server
if (size == 0 || (!size.HasValue && _fileStream.Length == 0))
{
_dataChunks = null;
_overlapped = new SafeNativeOverlapped(overlapped.Pack(IOCallback, null));
_overlapped = new SafeNativeOverlapped(boundHandle,
boundHandle.AllocateNativeOverlapped(IOCallback, this, null));
}
else
{
@ -206,7 +207,8 @@ namespace Microsoft.Net.Http.Server
}
// This call will pin needed memory
_overlapped = new SafeNativeOverlapped(overlapped.Pack(IOCallback, objectsToPin));
_overlapped = new SafeNativeOverlapped(boundHandle,
boundHandle.AllocateNativeOverlapped(IOCallback, this, objectsToPin));
if (chunked)
{
@ -318,9 +320,7 @@ namespace Microsoft.Net.Http.Server
private static unsafe void Callback(uint errorCode, uint numBytes, NativeOverlapped* nativeOverlapped)
{
Overlapped callbackOverlapped = Overlapped.Unpack(nativeOverlapped);
ResponseStreamAsyncResult asyncResult = callbackOverlapped.AsyncResult as ResponseStreamAsyncResult;
var asyncResult = (ResponseStreamAsyncResult)ThreadPoolBoundHandle.GetNativeOverlappedState(nativeOverlapped);
IOCompleted(asyncResult, errorCode, numBytes);
}

Просмотреть файл

@ -74,6 +74,7 @@ namespace Microsoft.Net.Http.Server
private ILogger _logger;
private SafeHandle _requestQueueHandle;
private ThreadPoolBoundHandle _boundHandle;
private volatile State _state; // m_State is set only within lock blocks, but often read outside locks.
private bool _ignoreWriteExceptions;
@ -141,6 +142,11 @@ namespace Microsoft.Net.Http.Server
}
}
internal ThreadPoolBoundHandle BoundHandle
{
get { return _boundHandle; }
}
internal ulong UrlGroupId
{
get { return _urlGroupId; }
@ -523,7 +529,7 @@ namespace Microsoft.Net.Http.Server
}
_requestQueueHandle = requestQueueHandle;
ThreadPool.BindHandle(_requestQueueHandle);
_boundHandle = ThreadPoolBoundHandle.BindHandle(_requestQueueHandle);
}
private unsafe void CloseRequestQueueHandle()
@ -532,6 +538,10 @@ namespace Microsoft.Net.Http.Server
{
_requestQueueHandle.Dispose();
}
if (_boundHandle != null)
{
_boundHandle.Dispose();
}
}
/// <summary>
@ -667,11 +677,10 @@ namespace Microsoft.Net.Http.Server
// Debug.WriteLine("Server: Registering connection for disconnect for connection ID: " + connectionId);
// Create a nativeOverlapped callback so we can register for disconnect callback
var overlapped = new Overlapped();
var cts = new CancellationTokenSource();
SafeNativeOverlapped nativeOverlapped = null;
nativeOverlapped = new SafeNativeOverlapped(overlapped.UnsafePack(
nativeOverlapped = new SafeNativeOverlapped(_boundHandle, _boundHandle.AllocateNativeOverlapped(
(errorCode, numBytes, overlappedPtr) =>
{
// Debug.WriteLine("Server: http.sys disconnect callback fired for connection ID: " + connectionId);
@ -693,7 +702,7 @@ namespace Microsoft.Net.Http.Server
cts.Dispose();
},
null));
null, null));
uint statusCode;
try

Просмотреть файл

@ -1,97 +0,0 @@
// Copyright (c) Microsoft Open Technologies, Inc.
// All Rights Reserved
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF
// TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
// NON-INFRINGEMENT.
// See the Apache 2 License for the specific language governing
// permissions and limitations under the License.
//------------------------------------------------------------------------------
// <copyright company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
using System;
using System.Runtime.InteropServices;
using System.Threading;
namespace Microsoft.Net.WebSockets
{
internal class SafeNativeOverlapped : SafeHandle
{
internal static readonly SafeNativeOverlapped Zero = new SafeNativeOverlapped();
internal SafeNativeOverlapped()
: this(IntPtr.Zero)
{
}
internal unsafe SafeNativeOverlapped(NativeOverlapped* handle)
: this((IntPtr)handle)
{
}
internal SafeNativeOverlapped(IntPtr handle)
: base(IntPtr.Zero, true)
{
SetHandle(handle);
}
public override bool IsInvalid
{
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);
// Do not call free durring AppDomain shutdown, there may be an outstanding operation.
// Overlapped will take care calling free when the native callback completes.
if (oldHandle != IntPtr.Zero && !HasShutdownStarted)
{
unsafe
{
Overlapped.Free((NativeOverlapped*)oldHandle);
}
}
return true;
}
internal static bool HasShutdownStarted
{
get
{
return Environment.HasShutdownStarted
#if !DNXCORE50
|| AppDomain.CurrentDomain.IsFinalizingForUnload()
#endif
;
}
}
}
}

Просмотреть файл

@ -20,7 +20,6 @@
"System.Security.Cryptography.Hashing.Algorithms": "4.0.0-beta-*",
"System.Text.Encoding.Extensions": "4.0.10-beta-*",
"System.Threading": "4.0.10-beta-*",
"System.Threading.Overlapped": "4.0.0-beta-*",
"System.Threading.Tasks": "4.0.10-beta-*",
"System.Threading.Timer": "4.0.0-beta-*",
"System.Threading.ThreadPool": "4.0.10-beta-*"