diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Http/Listener.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Http/Listener.cs index 818807a203..7fee42cec3 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Http/Listener.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Http/Listener.cs @@ -29,8 +29,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http var tcs = new TaskCompletionSource(this); - Thread.Post(tcs2 => + Thread.Post(state => { + var tcs2 = (TaskCompletionSource)state; try { var listener = ((Listener)tcs2.Task.AsyncState); diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Http/ListenerPrimary.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Http/ListenerPrimary.cs index 30b27342d7..3e4c86c627 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Http/ListenerPrimary.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Http/ListenerPrimary.cs @@ -46,7 +46,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http private void PostCallback() { ListenPipe = new UvPipeHandle(Log); - ListenPipe.Init(Thread.Loop, false); + ListenPipe.Init(Thread.Loop, Thread.QueueCloseHandle, false); ListenPipe.Bind(_pipeName); ListenPipe.Listen(Constants.ListenBacklog, (pipe, status, error, state) => ((ListenerPrimary)state).OnListenPipe(pipe, status, error), this); @@ -60,7 +60,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http } var dispatchPipe = new UvPipeHandle(Log); - dispatchPipe.Init(Thread.Loop, true); + dispatchPipe.Init(Thread.Loop, Thread.QueueCloseHandle, true); try { diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Http/ListenerSecondary.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Http/ListenerSecondary.cs index a096dea1a1..8d21c16dcd 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Http/ListenerSecondary.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Http/ListenerSecondary.cs @@ -42,7 +42,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http DispatchPipe = new UvPipeHandle(Log); var tcs = new TaskCompletionSource(this); - Thread.Post(tcs2 => StartCallback(tcs2), tcs); + Thread.Post(state => StartCallback((TaskCompletionSource)state), tcs); return tcs.Task; } @@ -56,7 +56,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http { try { - DispatchPipe.Init(Thread.Loop, true); + DispatchPipe.Init(Thread.Loop, Thread.QueueCloseHandle, true); var connect = new UvConnectRequest(Log); connect.Init(Thread.Loop); connect.Connect( diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Http/PipeListener.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Http/PipeListener.cs index 19a10c552f..3ee24032d6 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Http/PipeListener.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Http/PipeListener.cs @@ -23,7 +23,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http protected override UvStreamHandle CreateListenSocket() { var socket = new UvPipeHandle(Log); - socket.Init(Thread.Loop, false); + socket.Init(Thread.Loop, Thread.QueueCloseHandle, false); socket.Bind(ServerAddress.UnixPipePath); socket.Listen(Constants.ListenBacklog, (stream, status, error, state) => ConnectionCallback(stream, status, error, state), this); return socket; @@ -40,7 +40,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http try { - acceptSocket.Init(Thread.Loop, false); + acceptSocket.Init(Thread.Loop, Thread.QueueCloseHandle, false); listenSocket.Accept(acceptSocket); DispatchConnection(acceptSocket); } diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Http/PipeListenerPrimary.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Http/PipeListenerPrimary.cs index 4381a43c8b..07d353119f 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Http/PipeListenerPrimary.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Http/PipeListenerPrimary.cs @@ -23,7 +23,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http protected override UvStreamHandle CreateListenSocket() { var socket = new UvPipeHandle(Log); - socket.Init(Thread.Loop, false); + socket.Init(Thread.Loop, Thread.QueueCloseHandle, false); socket.Bind(ServerAddress.UnixPipePath); socket.Listen(Constants.ListenBacklog, (stream, status, error, state) => ConnectionCallback(stream, status, error, state), this); return socket; @@ -40,7 +40,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http try { - acceptSocket.Init(Thread.Loop, false); + acceptSocket.Init(Thread.Loop, Thread.QueueCloseHandle, false); listenSocket.Accept(acceptSocket); DispatchConnection(acceptSocket); } diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Http/PipeListenerSecondary.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Http/PipeListenerSecondary.cs index 3ca23ea6fc..1ec2373b4c 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Http/PipeListenerSecondary.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Http/PipeListenerSecondary.cs @@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http protected override UvStreamHandle CreateAcceptSocket() { var acceptSocket = new UvPipeHandle(Log); - acceptSocket.Init(Thread.Loop, false); + acceptSocket.Init(Thread.Loop, Thread.QueueCloseHandle, false); return acceptSocket; } } diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Http/SocketOutput.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Http/SocketOutput.cs index bab2689334..4ed52a12b7 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Http/SocketOutput.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Http/SocketOutput.cs @@ -314,7 +314,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http private void ScheduleWrite() { - _thread.Post(_this => _this.WriteAllPending(), this); + _thread.Post(state => ((SocketOutput)state).WriteAllPending(), this); } // This is called on the libuv event loop diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Infrastructure/KestrelThread.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Infrastructure/KestrelThread.cs index 7933e11e84..e6a40d024a 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Infrastructure/KestrelThread.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Infrastructure/KestrelThread.cs @@ -24,9 +24,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel // otherwise it needs to wait till the next pass of the libuv loop private const int _maxLoops = 8; - private static readonly Action _threadCallbackAdapter = (callback, state) => ((Action)callback).Invoke((KestrelThread)state); - private static readonly Action _socketCallbackAdapter = (callback, state) => ((Action)callback).Invoke((SocketOutput)state); - private static readonly Action _tcsCallbackAdapter = (callback, state) => ((Action>)callback).Invoke((TaskCompletionSource)state); + private static readonly Action _postCallbackAdapter = (callback, state) => ((Action)callback).Invoke(state); private static readonly Action _postAsyncCallbackAdapter = (callback, state) => ((Action)callback).Invoke(state); private readonly KestrelEngine _engine; @@ -56,12 +54,16 @@ namespace Microsoft.AspNetCore.Server.Kestrel _thread = new Thread(ThreadStart); _thread.Name = "KestrelThread - libuv"; QueueCloseHandle = PostCloseHandle; + QueueCloseAsyncHandle = EnqueueCloseHandle; } public UvLoopHandle Loop { get { return _loop; } } + public ExceptionDispatchInfo FatalError { get { return _closeError; } } - public Action, IntPtr> QueueCloseHandle { get; internal set; } + public Action, IntPtr> QueueCloseHandle { get; } + + private Action, IntPtr> QueueCloseAsyncHandle { get; } public Task StartAsync() { @@ -137,41 +139,23 @@ namespace Microsoft.AspNetCore.Server.Kestrel _loop.Stop(); } + public void Post(Action callback, object state) + { + lock (_workSync) + { + _workAdding.Enqueue(new Work + { + CallbackAdapter = _postCallbackAdapter, + Callback = callback, + State = state + }); + } + _post.Send(); + } + private void Post(Action callback) { - lock (_workSync) - { - _workAdding.Enqueue(new Work { CallbackAdapter = _threadCallbackAdapter, Callback = callback, State = this }); - } - _post.Send(); - } - - public void Post(Action callback, SocketOutput state) - { - lock (_workSync) - { - _workAdding.Enqueue(new Work - { - CallbackAdapter = _socketCallbackAdapter, - Callback = callback, - State = state - }); - } - _post.Send(); - } - - public void Post(Action> callback, TaskCompletionSource state) - { - lock (_workSync) - { - _workAdding.Enqueue(new Work - { - CallbackAdapter = _tcsCallbackAdapter, - Callback = callback, - State = state - }); - } - _post.Send(); + Post(thread => callback((KestrelThread)thread), this); } public Task PostAsync(Action callback, object state) @@ -192,12 +176,17 @@ namespace Microsoft.AspNetCore.Server.Kestrel } private void PostCloseHandle(Action callback, IntPtr handle) + { + EnqueueCloseHandle(callback, handle); + _post.Send(); + } + + private void EnqueueCloseHandle(Action callback, IntPtr handle) { lock (_workSync) { _closeHandleAdding.Enqueue(new CloseHandle { Callback = callback, Handle = handle }); } - _post.Send(); } private void ThreadStart(object parameter) @@ -206,7 +195,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel try { _loop.Init(_engine.Libuv); - _post.Init(_loop, OnPost); + _post.Init(_loop, OnPost, EnqueueCloseHandle); tcs.SetResult(0); } catch (Exception ex) @@ -230,18 +219,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel _post.Reference(); _post.Dispose(); - _engine.Libuv.walk( - _loop, - (ptr, arg) => - { - var handle = UvMemory.FromIntPtr(ptr); - if (handle != _post) - { - handle.Dispose(); - } - }, - IntPtr.Zero); - // Ensure the Dispose operations complete in the event loop. var ran2 = _loop.Run(); @@ -307,6 +284,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel return wasWork; } + private bool DoPostCloseHandle() { Queue queue; @@ -333,7 +311,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel } } - return wasWork; + return wasWork; } private struct Work @@ -343,6 +321,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel public object State; public TaskCompletionSource Completion; } + private struct CloseHandle { public Action Callback; diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Networking/Libuv.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Networking/Libuv.cs index 279d4885cf..8625350497 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Networking/Libuv.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Networking/Libuv.cs @@ -30,6 +30,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Networking _uv_close = NativeDarwinMonoMethods.uv_close; _uv_async_init = NativeDarwinMonoMethods.uv_async_init; _uv_async_send = NativeDarwinMonoMethods.uv_async_send; + _uv_unsafe_async_send = NativeDarwinMonoMethods.uv_unsafe_async_send; _uv_tcp_init = NativeDarwinMonoMethods.uv_tcp_init; _uv_tcp_bind = NativeDarwinMonoMethods.uv_tcp_bind; _uv_tcp_open = NativeDarwinMonoMethods.uv_tcp_open; @@ -71,6 +72,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Networking _uv_close = NativeMethods.uv_close; _uv_async_init = NativeMethods.uv_async_init; _uv_async_send = NativeMethods.uv_async_send; + _uv_unsafe_async_send = NativeMethods.uv_unsafe_async_send; _uv_tcp_init = NativeMethods.uv_tcp_init; _uv_tcp_bind = NativeMethods.uv_tcp_bind; _uv_tcp_open = NativeMethods.uv_tcp_open; @@ -207,6 +209,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Networking Check(_uv_async_send(handle)); } + protected Func _uv_unsafe_async_send; + public void unsafe_async_send(IntPtr handle) + { + Check(_uv_unsafe_async_send(handle)); + } + protected Func _uv_tcp_init; public void tcp_init(UvLoopHandle loop, UvTcpHandle handle) { @@ -510,6 +518,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Networking [DllImport("libuv", CallingConvention = CallingConvention.Cdecl)] public extern static int uv_async_send(UvAsyncHandle handle); + [DllImport("libuv", CallingConvention = CallingConvention.Cdecl, EntryPoint = "uv_async_send")] + public extern static int uv_unsafe_async_send(IntPtr handle); + [DllImport("libuv", CallingConvention = CallingConvention.Cdecl)] public static extern int uv_tcp_init(UvLoopHandle loop, UvTcpHandle handle); @@ -618,6 +629,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Networking [DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)] public extern static int uv_async_send(UvAsyncHandle handle); + [DllImport("__Internal", CallingConvention = CallingConvention.Cdecl, EntryPoint = "uv_async_send")] + public extern static int uv_unsafe_async_send(IntPtr handle); + [DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)] public static extern int uv_tcp_init(UvLoopHandle loop, UvTcpHandle handle); diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvAsyncHandle.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvAsyncHandle.cs index d78973a847..3215a8730c 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvAsyncHandle.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvAsyncHandle.cs @@ -2,27 +2,33 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Diagnostics; +using System.Threading; using Microsoft.AspNetCore.Server.Kestrel.Infrastructure; namespace Microsoft.AspNetCore.Server.Kestrel.Networking { public class UvAsyncHandle : UvHandle { + private static readonly Libuv.uv_close_cb _destroyMemory = (handle) => DestroyMemory(handle); + private static readonly Libuv.uv_async_cb _uv_async_cb = (handle) => AsyncCb(handle); private Action _callback; + private Action, IntPtr> _queueCloseHandle; public UvAsyncHandle(IKestrelTrace logger) : base(logger) { } - public void Init(UvLoopHandle loop, Action callback) + public void Init(UvLoopHandle loop, Action callback, Action, IntPtr> queueCloseHandle) { CreateMemory( - loop.Libuv, - loop.ThreadId, + loop.Libuv, + loop.ThreadId, loop.Libuv.handle_size(Libuv.HandleType.ASYNC)); _callback = callback; + _queueCloseHandle = queueCloseHandle; _uv.async_init(loop, this, _uv_async_cb); } @@ -35,5 +41,33 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Networking { FromIntPtr(handle)._callback.Invoke(); } + + protected override bool ReleaseHandle() + { + var memory = handle; + if (memory != IntPtr.Zero) + { + handle = IntPtr.Zero; + + if (Thread.CurrentThread.ManagedThreadId == ThreadId) + { + _uv.close(memory, _destroyMemory); + } + else if (_queueCloseHandle != null) + { + // This can be called from the finalizer. + // Ensure the closure doesn't reference "this". + var uv = _uv; + _queueCloseHandle(memory2 => uv.close(memory2, _destroyMemory), memory); + uv.unsafe_async_send(memory); + } + else + { + Debug.Assert(false, "UvAsyncHandle not initialized with queueCloseHandle action"); + return false; + } + } + return true; + } } } diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvHandle.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvHandle.cs index 65f3c43580..d672189698 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvHandle.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvHandle.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Diagnostics; using System.Threading; using Microsoft.AspNetCore.Server.Kestrel.Infrastructure; @@ -44,6 +45,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Networking var uv = _uv; _queueCloseHandle(memory2 => uv.close(memory2, _destroyMemory), memory); } + else + { + Debug.Assert(false, "UvHandle not initialized with queueCloseHandle action"); + return false; + } } return true; } diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvLoopHandle.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvLoopHandle.cs index 3cf357af9b..e368c6ea34 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvLoopHandle.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvLoopHandle.cs @@ -7,7 +7,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Infrastructure; namespace Microsoft.AspNetCore.Server.Kestrel.Networking { - public class UvLoopHandle : UvHandle + public class UvLoopHandle : UvMemory { public UvLoopHandle(IKestrelTrace logger) : base(logger) { @@ -35,7 +35,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Networking unsafe protected override bool ReleaseHandle() { - var memory = this.handle; + var memory = handle; if (memory != IntPtr.Zero) { // loop_close clears the gcHandlePtr @@ -46,6 +46,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Networking DestroyMemory(memory, gcHandlePtr); } + return true; } } diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvMemory.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvMemory.cs index c9a62462cf..162fed17e8 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvMemory.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvMemory.cs @@ -87,6 +87,5 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Networking GCHandle gcHandle = GCHandle.FromIntPtr(*(IntPtr*)handle); return (THandle)gcHandle.Target; } - } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvPipeHandle.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvPipeHandle.cs index af143536a4..6604dfbb28 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvPipeHandle.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvPipeHandle.cs @@ -13,24 +13,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Networking { } - public void Init(UvLoopHandle loop, bool ipc) - { - CreateMemory( - loop.Libuv, - loop.ThreadId, - loop.Libuv.handle_size(Libuv.HandleType.NAMED_PIPE)); - - _uv.pipe_init(loop, this, ipc); - } - - public void Init(UvLoopHandle loop, Action, IntPtr> queueCloseHandle) + public void Init(UvLoopHandle loop, Action, IntPtr> queueCloseHandle, bool ipc = false) { CreateHandle( loop.Libuv, loop.ThreadId, - loop.Libuv.handle_size(Libuv.HandleType.TCP), queueCloseHandle); + loop.Libuv.handle_size(Libuv.HandleType.NAMED_PIPE), queueCloseHandle); - _uv.pipe_init(loop, this, false); + _uv.pipe_init(loop, this, ipc); } public void Bind(string name) diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvStreamHandle.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvStreamHandle.cs index 3b88c74a16..266fd96a13 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvStreamHandle.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvStreamHandle.cs @@ -15,13 +15,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Networking private readonly static Libuv.uv_alloc_cb _uv_alloc_cb = (IntPtr handle, int suggested_size, out Libuv.uv_buf_t buf) => UvAllocCb(handle, suggested_size, out buf); private readonly static Libuv.uv_read_cb _uv_read_cb = (IntPtr handle, int status, ref Libuv.uv_buf_t buf) => UvReadCb(handle, status, ref buf); - public Action _listenCallback; - public object _listenState; + private Action _listenCallback; + private object _listenState; private GCHandle _listenVitality; - public Func _allocCallback; - public Action _readCallback; - public object _readState; + private Func _allocCallback; + private Action _readCallback; + private object _readState; private GCHandle _readVitality; protected UvStreamHandle(IKestrelTrace logger) : base(logger) diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvTcpHandle.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvTcpHandle.cs index ec201a3627..6e7e9b2549 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvTcpHandle.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Networking/UvTcpHandle.cs @@ -14,16 +14,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Networking { } - public void Init(UvLoopHandle loop) - { - CreateMemory( - loop.Libuv, - loop.ThreadId, - loop.Libuv.handle_size(Libuv.HandleType.TCP)); - - _uv.tcp_init(loop, this); - } - public void Init(UvLoopHandle loop, Action, IntPtr> queueCloseHandle) { CreateHandle( diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/MultipleLoopTests.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/MultipleLoopTests.cs index 6c4d2e8ed0..f75079f57e 100644 --- a/test/Microsoft.AspNetCore.Server.KestrelTests/MultipleLoopTests.cs +++ b/test/Microsoft.AspNetCore.Server.KestrelTests/MultipleLoopTests.cs @@ -21,13 +21,14 @@ namespace Microsoft.AspNetCore.Server.KestrelTests _logger = engine.Log; } + [Fact] public void InitAndCloseServerPipe() { var loop = new UvLoopHandle(_logger); var pipe = new UvPipeHandle(_logger); loop.Init(_uv); - pipe.Init(loop, true); + pipe.Init(loop, (a, b) => { }, true); pipe.Bind(@"\\.\pipe\InitAndCloseServerPipe"); pipe.Dispose(); @@ -38,18 +39,19 @@ namespace Microsoft.AspNetCore.Server.KestrelTests } + [Fact(Skip = "Test needs to be fixed (UvException: Error -4082 EBUSY resource busy or locked from loop_close)")] public void ServerPipeListenForConnections() { var loop = new UvLoopHandle(_logger); var serverListenPipe = new UvPipeHandle(_logger); loop.Init(_uv); - serverListenPipe.Init(loop, false); + serverListenPipe.Init(loop, (a, b) => { }, false); serverListenPipe.Bind(@"\\.\pipe\ServerPipeListenForConnections"); serverListenPipe.Listen(128, (_1, status, error, _2) => { var serverConnectionPipe = new UvPipeHandle(_logger); - serverConnectionPipe.Init(loop, true); + serverConnectionPipe.Init(loop, (a, b) => { }, true); try { serverListenPipe.Accept(serverConnectionPipe); @@ -92,7 +94,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests var connect = new UvConnectRequest(new KestrelTrace(new TestKestrelTrace())); loop2.Init(_uv); - clientConnectionPipe.Init(loop2, true); + clientConnectionPipe.Init(loop2, (a, b) => { }, true); connect.Init(loop2); connect.Connect(clientConnectionPipe, @"\\.\pipe\ServerPipeListenForConnections", (_1, status, error, _2) => { @@ -120,6 +122,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests } + [Fact(Skip = "Test needs to be fixed (UvException: Error -4088 EAGAIN resource temporarily unavailable from accept)")] public void ServerPipeDispatchConnections() { var pipeName = @"\\.\pipe\ServerPipeDispatchConnections" + Guid.NewGuid().ToString("n"); @@ -132,12 +135,12 @@ namespace Microsoft.AspNetCore.Server.KestrelTests var serverConnectionTcpDisposedEvent = new ManualResetEvent(false); var serverListenPipe = new UvPipeHandle(_logger); - serverListenPipe.Init(loop, false); + serverListenPipe.Init(loop, (a, b) => { }, false); serverListenPipe.Bind(pipeName); serverListenPipe.Listen(128, (_1, status, error, _2) => { serverConnectionPipe = new UvPipeHandle(_logger); - serverConnectionPipe.Init(loop, true); + serverConnectionPipe.Init(loop, (a, b) => { }, true); try { serverListenPipe.Accept(serverConnectionPipe); @@ -152,13 +155,13 @@ namespace Microsoft.AspNetCore.Server.KestrelTests }, null); var serverListenTcp = new UvTcpHandle(_logger); - serverListenTcp.Init(loop); + serverListenTcp.Init(loop, (a, b) => { }); var address = ServerAddress.FromUrl("http://localhost:54321/"); serverListenTcp.Bind(address); serverListenTcp.Listen(128, (_1, status, error, _2) => { var serverConnectionTcp = new UvTcpHandle(_logger); - serverConnectionTcp.Init(loop); + serverConnectionTcp.Init(loop, (a, b) => { }); serverListenTcp.Accept(serverConnectionTcp); serverConnectionPipeAcceptedEvent.WaitOne(); @@ -188,7 +191,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests var connect = new UvConnectRequest(new KestrelTrace(new TestKestrelTrace())); loop2.Init(_uv); - clientConnectionPipe.Init(loop2, true); + clientConnectionPipe.Init(loop2, (a, b) => { }, true); connect.Init(loop2); connect.Connect(clientConnectionPipe, pipeName, (_1, status, error, _2) => { @@ -208,7 +211,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests return; } var clientConnectionTcp = new UvTcpHandle(_logger); - clientConnectionTcp.Init(loop2); + clientConnectionTcp.Init(loop2, (a, b) => { }); clientConnectionPipe.Accept(clientConnectionTcp); var buf2 = loop2.Libuv.buf_init(Marshal.AllocHGlobal(64), 64); clientConnectionTcp.ReadStart( diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/NetworkingTests.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/NetworkingTests.cs index 642d4c7729..7e05b5a533 100644 --- a/test/Microsoft.AspNetCore.Server.KestrelTests/NetworkingTests.cs +++ b/test/Microsoft.AspNetCore.Server.KestrelTests/NetworkingTests.cs @@ -47,7 +47,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests { called = true; trigger.Dispose(); - }); + }, (a, b) => { }); trigger.Send(); loop.Run(); loop.Dispose(); @@ -60,7 +60,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests var loop = new UvLoopHandle(_logger); loop.Init(_uv); var tcp = new UvTcpHandle(_logger); - tcp.Init(loop); + tcp.Init(loop, (a, b) => { }); var address = ServerAddress.FromUrl("http://localhost:0/"); tcp.Bind(address); tcp.Dispose(); @@ -75,14 +75,14 @@ namespace Microsoft.AspNetCore.Server.KestrelTests var loop = new UvLoopHandle(_logger); loop.Init(_uv); var tcp = new UvTcpHandle(_logger); - tcp.Init(loop); + tcp.Init(loop, (a, b) => { }); var port = TestServer.GetNextPort(); var address = ServerAddress.FromUrl($"http://localhost:{port}/"); tcp.Bind(address); tcp.Listen(10, (stream, status, error, state) => { var tcp2 = new UvTcpHandle(_logger); - tcp2.Init(loop); + tcp2.Init(loop, (a, b) => { }); stream.Accept(tcp2); tcp2.Dispose(); stream.Dispose(); @@ -117,15 +117,14 @@ namespace Microsoft.AspNetCore.Server.KestrelTests var loop = new UvLoopHandle(_logger); loop.Init(_uv); var tcp = new UvTcpHandle(_logger); - tcp.Init(loop); + tcp.Init(loop, (a, b) => { }); var port = TestServer.GetNextPort(); var address = ServerAddress.FromUrl($"http://localhost:{port}/"); tcp.Bind(address); tcp.Listen(10, (_, status, error, state) => { - Console.WriteLine("Connected"); var tcp2 = new UvTcpHandle(_logger); - tcp2.Init(loop); + tcp2.Init(loop, (a, b) => { }); tcp.Accept(tcp2); var data = Marshal.AllocCoTaskMem(500); tcp2.ReadStart( @@ -140,7 +139,6 @@ namespace Microsoft.AspNetCore.Server.KestrelTests null); tcp.Dispose(); }, null); - Console.WriteLine("Task.Run"); var t = Task.Run(async () => { var socket = new Socket( @@ -179,15 +177,14 @@ namespace Microsoft.AspNetCore.Server.KestrelTests var loop = new UvLoopHandle(_logger); loop.Init(_uv); var tcp = new UvTcpHandle(_logger); - tcp.Init(loop); + tcp.Init(loop, (a, b) => { }); var port = TestServer.GetNextPort(); var address = ServerAddress.FromUrl($"http://localhost:{port}/"); tcp.Bind(address); tcp.Listen(10, (_, status, error, state) => { - Console.WriteLine("Connected"); var tcp2 = new UvTcpHandle(_logger); - tcp2.Init(loop); + tcp2.Init(loop, (a, b) => { }); tcp.Accept(tcp2); var data = Marshal.AllocCoTaskMem(500); tcp2.ReadStart( @@ -227,7 +224,6 @@ namespace Microsoft.AspNetCore.Server.KestrelTests null); tcp.Dispose(); }, null); - Console.WriteLine("Task.Run"); var t = Task.Run(async () => { var socket = new Socket( @@ -268,9 +264,6 @@ namespace Microsoft.AspNetCore.Server.KestrelTests #else var count = await socket.ReceiveAsync(new[] { buffer }, SocketFlags.None); #endif - Console.WriteLine("count {0} {1}", - count, - System.Text.Encoding.ASCII.GetString(buffer.Array, 0, count)); if (count <= 0) break; } socket.Dispose();