From 30ec2cb0b1f9f5ebf570031df0da080a936ea73d Mon Sep 17 00:00:00 2001 From: Louis DeJardin Date: Thu, 17 Sep 2015 18:53:35 -0700 Subject: [PATCH] Harden framing epilog * Connection no longer needes Frame's processing Task * Any exceptions from unusual processing is logged --- .../Http/Connection.cs | 2 +- .../Http/Frame.cs | 124 ++++++++++-------- 2 files changed, 72 insertions(+), 54 deletions(-) diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/Connection.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/Connection.cs index c9d5ce2d24..ce231cafbf 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/Connection.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/Connection.cs @@ -40,7 +40,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http SocketInput = new SocketInput(Memory2); SocketOutput = new SocketOutput(Thread, _socket, _connectionId, Log); _frame = new Frame(this); - _frameTask = Task.Run(_frame.ProcessFraming); + Task.Run(_frame.ProcessFraming); _socket.ReadStart(_allocCallback, _readCallback, this); } diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.cs index 45e1807778..c3eb8d53d8 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.cs @@ -9,6 +9,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNet.Server.Kestrel.Infrastructure; +using Microsoft.Framework.Logging; using Microsoft.Framework.Primitives; // ReSharper disable AccessToModifiedClosure @@ -98,73 +99,90 @@ namespace Microsoft.AspNet.Server.Kestrel.Http _responseHeaders.HeaderDate = DateTime.UtcNow.ToString("r"); } - public async Task ProcessFraming() + public async void ProcessFraming() { - var terminated = false; - while (!terminated) + try { - while (!terminated && !TakeStartLine(SocketInput)) + var terminated = false; + while (!terminated) { - terminated = SocketInput.RemoteIntakeFin; - if (!terminated) + while (!terminated && !TakeStartLine(SocketInput)) { - await SocketInput; - } - } - - while (!terminated && !TakeMessageHeaders(SocketInput)) - { - terminated = SocketInput.RemoteIntakeFin; - if (!terminated) - { - await SocketInput; - } - } - - if (!terminated) - { - MessageBody = MessageBody.For(HttpVersion, _requestHeaders, this); - _keepAlive = MessageBody.RequestKeepAlive; - RequestBody = new FrameRequestStream(MessageBody); - ResponseBody = new FrameResponseStream(this); - DuplexStream = new FrameDuplexStream(RequestBody, ResponseBody); - - Exception error = null; - try - { - await Application.Invoke(this).ConfigureAwait(false); - - // Trigger FireOnStarting if ProduceStart hasn't been called yet. - // We call it here, so it can go through our normal error handling - // and respond with a 500 if an OnStarting callback throws. - if (!_responseStarted) + terminated = SocketInput.RemoteIntakeFin; + if (!terminated) { - FireOnStarting(); + await SocketInput; } } - catch (Exception ex) + + while (!terminated && !TakeMessageHeaders(SocketInput)) { - error = ex; - } - finally - { - FireOnCompleted(); - ProduceEnd(error); + terminated = SocketInput.RemoteIntakeFin; + if (!terminated) + { + await SocketInput; + } } - terminated = !_keepAlive; + if (!terminated) + { + MessageBody = MessageBody.For(HttpVersion, _requestHeaders, this); + _keepAlive = MessageBody.RequestKeepAlive; + RequestBody = new FrameRequestStream(MessageBody); + ResponseBody = new FrameResponseStream(this); + DuplexStream = new FrameDuplexStream(RequestBody, ResponseBody); + + Exception error = null; + try + { + await Application.Invoke(this).ConfigureAwait(false); + + // Trigger FireOnStarting if ProduceStart hasn't been called yet. + // We call it here, so it can go through our normal error handling + // and respond with a 500 if an OnStarting callback throws. + if (!_responseStarted) + { + FireOnStarting(); + } + } + catch (Exception ex) + { + error = ex; + } + finally + { + FireOnCompleted(); + ProduceEnd(error); + } + + terminated = !_keepAlive; + } + + Reset(); } - - Reset(); } + catch (Exception ex) + { + Log.LogVerbose("Connection processing ended abnormally", ex); + } + finally + { + try + { + // Inform client no more data will ever arrive + ConnectionControl.End(ProduceEndType.SocketShutdownSend); - // Connection Terminated! - ConnectionControl.End(ProduceEndType.SocketShutdownSend); + // Wait for client to either disconnect or send unexpected data + await SocketInput; - // Wait for client to disconnect, or to receive unexpected data - await SocketInput; - - ConnectionControl.End(ProduceEndType.SocketDisconnect); + // Dispose socket + ConnectionControl.End(ProduceEndType.SocketDisconnect); + } + catch(Exception ex) + { + Log.LogVerbose("Connection shutdown abnormally", ex); + } + } } public void OnStarting(Func callback, object state)