diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Infrastructure/KestrelThread.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Infrastructure/KestrelThread.cs index 083ecf29f6..4d76a18c67 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Infrastructure/KestrelThread.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Infrastructure/KestrelThread.cs @@ -279,7 +279,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal try { - var ran1 = _loop.Run(); + _loop.Run(); if (_stopImmediate) { // thread-abort form of exit, resources will be leaked @@ -291,7 +291,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal _post.Dispose(); // Ensure the Dispose operations complete in the event loop. - var ran2 = _loop.Run(); + _loop.Run(); _loop.Dispose(); } diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Networking/Libuv.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Networking/Libuv.cs index ee2a25855e..9c918491cc 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Networking/Libuv.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Networking/Libuv.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.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Networking @@ -61,50 +62,57 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Networking public readonly bool IsWindows; - public int Check(int statusCode) - { - Exception error; - var result = Check(statusCode, out error); - if (error != null) - { - throw error; - } - return statusCode; - } - - public int Check(int statusCode, out Exception error) + public void ThrowIfErrored(int statusCode) { + // Note: method is explicitly small so the success case is easily inlined if (statusCode < 0) { - var errorName = err_name(statusCode); - var errorDescription = strerror(statusCode); - error = new UvException("Error " + statusCode + " " + errorName + " " + errorDescription, statusCode); + ThrowError(statusCode); } - else - { - error = null; - } - return statusCode; + } + + private void ThrowError(int statusCode) + { + // Note: only has one throw block so it will marked as "Does not return" by the jit + // and not inlined into previous function, while also marking as a function + // that does not need cpu register prep to call (see: https://github.com/dotnet/coreclr/pull/6103) + throw GetError(statusCode); + } + + public void Check(int statusCode, out Exception error) + { + // Note: method is explicitly small so the success case is easily inlined + error = statusCode < 0 ? GetError(statusCode) : null; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private UvException GetError(int statusCode) + { + // Note: method marked as NoInlining so it doesn't bloat either of the two preceeding functions + // Check and ThrowError and alter their jit heuristics. + var errorName = err_name(statusCode); + var errorDescription = strerror(statusCode); + return new UvException("Error " + statusCode + " " + errorName + " " + errorDescription, statusCode); } protected Func _uv_loop_init; public void loop_init(UvLoopHandle handle) { - Check(_uv_loop_init(handle)); + ThrowIfErrored(_uv_loop_init(handle)); } protected Func _uv_loop_close; public void loop_close(UvLoopHandle handle) { handle.Validate(closed: true); - Check(_uv_loop_close(handle.InternalGetHandle())); + ThrowIfErrored(_uv_loop_close(handle.InternalGetHandle())); } protected Func _uv_run; - public int run(UvLoopHandle handle, int mode) + public void run(UvLoopHandle handle, int mode) { handle.Validate(); - return Check(_uv_run(handle, mode)); + ThrowIfErrored(_uv_run(handle, mode)); } protected Action _uv_stop; @@ -131,10 +139,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Networking [UnmanagedFunctionPointer(CallingConvention.Cdecl)] protected delegate int uv_fileno_func(UvHandle handle, ref IntPtr socket); protected uv_fileno_func _uv_fileno; - public int uv_fileno(UvHandle handle, ref IntPtr socket) + public void uv_fileno(UvHandle handle, ref IntPtr socket) { handle.Validate(); - return Check(_uv_fileno(handle, ref socket)); + ThrowIfErrored(_uv_fileno(handle, ref socket)); } [UnmanagedFunctionPointer(CallingConvention.Cdecl)] @@ -158,19 +166,19 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Networking { loop.Validate(); handle.Validate(); - Check(_uv_async_init(loop, handle, cb)); + ThrowIfErrored(_uv_async_init(loop, handle, cb)); } protected Func _uv_async_send; public void async_send(UvAsyncHandle handle) { - Check(_uv_async_send(handle)); + ThrowIfErrored(_uv_async_send(handle)); } protected Func _uv_unsafe_async_send; public void unsafe_async_send(IntPtr handle) { - Check(_uv_unsafe_async_send(handle)); + ThrowIfErrored(_uv_unsafe_async_send(handle)); } protected Func _uv_tcp_init; @@ -178,7 +186,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Networking { loop.Validate(); handle.Validate(); - Check(_uv_tcp_init(loop, handle)); + ThrowIfErrored(_uv_tcp_init(loop, handle)); } protected delegate int uv_tcp_bind_func(UvTcpHandle handle, ref SockAddr addr, int flags); @@ -186,7 +194,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Networking public void tcp_bind(UvTcpHandle handle, ref SockAddr addr, int flags) { handle.Validate(); - Check(_uv_tcp_bind(handle, ref addr, flags)); + ThrowIfErrored(_uv_tcp_bind(handle, ref addr, flags)); if (PlatformApis.IsWindows) { tcp_bind_windows_extras(handle); @@ -200,7 +208,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Networking const int SOCKET_ERROR = -1; var socket = IntPtr.Zero; - Check(_uv_fileno(handle, ref socket)); + ThrowIfErrored(_uv_fileno(handle, ref socket)); // Enable loopback fast-path for lower latency for localhost comms, like HttpPlatformHandler fronting // http://blogs.technet.com/b/wincat/archive/2012/12/05/fast-tcp-loopback-performance-and-low-latency-with-windows-server-2012-tcp-loopback-fast-path.aspx @@ -218,7 +226,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Networking } else { - Check(errorId); + ThrowIfErrored(errorId); } } } @@ -227,14 +235,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Networking public void tcp_open(UvTcpHandle handle, IntPtr hSocket) { handle.Validate(); - Check(_uv_tcp_open(handle, hSocket)); + ThrowIfErrored(_uv_tcp_open(handle, hSocket)); } protected Func _uv_tcp_nodelay; public void tcp_nodelay(UvTcpHandle handle, bool enable) { handle.Validate(); - Check(_uv_tcp_nodelay(handle, enable ? 1 : 0)); + ThrowIfErrored(_uv_tcp_nodelay(handle, enable ? 1 : 0)); } protected Func _uv_pipe_init; @@ -242,14 +250,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Networking { loop.Validate(); handle.Validate(); - Check(_uv_pipe_init(loop, handle, ipc ? -1 : 0)); + ThrowIfErrored(_uv_pipe_init(loop, handle, ipc ? -1 : 0)); } protected Func _uv_pipe_bind; public void pipe_bind(UvPipeHandle handle, string name) { handle.Validate(); - Check(_uv_pipe_bind(handle, name)); + ThrowIfErrored(_uv_pipe_bind(handle, name)); } [UnmanagedFunctionPointer(CallingConvention.Cdecl)] @@ -258,7 +266,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Networking public void listen(UvStreamHandle handle, int backlog, uv_connection_cb cb) { handle.Validate(); - Check(_uv_listen(handle, backlog, cb)); + ThrowIfErrored(_uv_listen(handle, backlog, cb)); } protected Func _uv_accept; @@ -266,7 +274,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Networking { server.Validate(); client.Validate(); - Check(_uv_accept(server, client)); + ThrowIfErrored(_uv_accept(server, client)); } [UnmanagedFunctionPointer(CallingConvention.Cdecl)] @@ -294,21 +302,23 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Networking public void read_start(UvStreamHandle handle, uv_alloc_cb alloc_cb, uv_read_cb read_cb) { handle.Validate(); - Check(_uv_read_start(handle, alloc_cb, read_cb)); + ThrowIfErrored(_uv_read_start(handle, alloc_cb, read_cb)); } protected Func _uv_read_stop; public void read_stop(UvStreamHandle handle) { handle.Validate(); - Check(_uv_read_stop(handle)); + ThrowIfErrored(_uv_read_stop(handle)); } protected Func _uv_try_write; public int try_write(UvStreamHandle handle, uv_buf_t[] bufs, int nbufs) { handle.Validate(); - return Check(_uv_try_write(handle, bufs, nbufs)); + var count = _uv_try_write(handle, bufs, nbufs); + ThrowIfErrored(count); + return count; } [UnmanagedFunctionPointer(CallingConvention.Cdecl)] @@ -320,7 +330,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Networking { req.Validate(); handle.Validate(); - Check(_uv_write(req, handle, bufs, nbufs, cb)); + ThrowIfErrored(_uv_write(req, handle, bufs, nbufs, cb)); } unsafe protected delegate int uv_write2_func(UvRequest req, UvStreamHandle handle, uv_buf_t* bufs, int nbufs, UvStreamHandle sendHandle, uv_write_cb cb); @@ -329,7 +339,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Networking { req.Validate(); handle.Validate(); - Check(_uv_write2(req, handle, bufs, nbufs, sendHandle, cb)); + ThrowIfErrored(_uv_write2(req, handle, bufs, nbufs, sendHandle, cb)); } [UnmanagedFunctionPointer(CallingConvention.Cdecl)] @@ -339,7 +349,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Networking { req.Validate(); handle.Validate(); - Check(_uv_shutdown(req, handle, cb)); + ThrowIfErrored(_uv_shutdown(req, handle, cb)); } protected Func _uv_err_name; @@ -376,16 +386,16 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Networking protected delegate int uv_ip4_addr_func(string ip, int port, out SockAddr addr); protected uv_ip4_addr_func _uv_ip4_addr; - public int ip4_addr(string ip, int port, out SockAddr addr, out Exception error) + public void ip4_addr(string ip, int port, out SockAddr addr, out Exception error) { - return Check(_uv_ip4_addr(ip, port, out addr), out error); + Check(_uv_ip4_addr(ip, port, out addr), out error); } protected delegate int uv_ip6_addr_func(string ip, int port, out SockAddr addr); protected uv_ip6_addr_func _uv_ip6_addr; - public int ip6_addr(string ip, int port, out SockAddr addr, out Exception error) + public void ip6_addr(string ip, int port, out SockAddr addr, out Exception error) { - return Check(_uv_ip6_addr(ip, port, out addr), out error); + Check(_uv_ip6_addr(ip, port, out addr), out error); } [UnmanagedFunctionPointer(CallingConvention.Cdecl)] @@ -402,7 +412,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Networking public void tcp_getsockname(UvTcpHandle handle, out SockAddr addr, ref int namelen) { handle.Validate(); - Check(_uv_tcp_getsockname(handle, out addr, ref namelen)); + ThrowIfErrored(_uv_tcp_getsockname(handle, out addr, ref namelen)); } public delegate int uv_tcp_getpeername_func(UvTcpHandle handle, out SockAddr addr, ref int namelen); @@ -410,7 +420,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Networking public void tcp_getpeername(UvTcpHandle handle, out SockAddr addr, ref int namelen) { handle.Validate(); - Check(_uv_tcp_getpeername(handle, out addr, ref namelen)); + ThrowIfErrored(_uv_tcp_getpeername(handle, out addr, ref namelen)); } public uv_buf_t buf_init(IntPtr memory, int len) diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Networking/UvLoopHandle.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Networking/UvLoopHandle.cs index 0d92f89770..25bb3701b0 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Networking/UvLoopHandle.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Networking/UvLoopHandle.cs @@ -23,9 +23,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Networking _uv.loop_init(this); } - public int Run(int mode = 0) + public void Run(int mode = 0) { - return _uv.run(this, mode); + _uv.run(this, mode); } public void Stop() diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Networking/UvStreamHandle.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Networking/UvStreamHandle.cs index 1a930f604d..698a693c60 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Networking/UvStreamHandle.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Networking/UvStreamHandle.cs @@ -128,7 +128,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Networking var stream = FromIntPtr(handle); Exception error; - status = stream.Libuv.Check(status, out error); + stream.Libuv.Check(status, out error); try {