Don't crash the server if a connection filter throws synchronously.

This commit is contained in:
Cesar Blum Silveira 2015-11-18 16:32:22 -08:00
parent efec0feda2
commit 307e020703
2 changed files with 64 additions and 18 deletions

View File

@ -78,25 +78,33 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
Address = ServerAddress
};
ConnectionFilter.OnConnection(_filterContext).ContinueWith((task, state) =>
try
{
var connection = (Connection)state;
ConnectionFilter.OnConnection(_filterContext).ContinueWith((task, state) =>
{
var connection = (Connection)state;
if (task.IsFaulted)
{
connection.Log.LogError("ConnectionFilter.OnConnection", task.Exception);
connection.ConnectionControl.End(ProduceEndType.SocketDisconnect);
}
else if (task.IsCanceled)
{
connection.Log.LogError("ConnectionFilter.OnConnection Canceled");
connection.ConnectionControl.End(ProduceEndType.SocketDisconnect);
}
else
{
connection.ApplyConnectionFilter();
}
}, this);
if (task.IsFaulted)
{
connection.Log.LogError("ConnectionFilter.OnConnection", task.Exception);
connection.ConnectionControl.End(ProduceEndType.SocketDisconnect);
}
else if (task.IsCanceled)
{
connection.Log.LogError("ConnectionFilter.OnConnection Canceled");
connection.ConnectionControl.End(ProduceEndType.SocketDisconnect);
}
else
{
connection.ApplyConnectionFilter();
}
}, this);
}
catch (Exception ex)
{
Log.LogError("ConnectionFilter.OnConnection", ex);
ConnectionControl.End(ProduceEndType.SocketDisconnect);
}
}
}

View File

@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
@ -80,7 +81,36 @@ namespace Microsoft.AspNet.Server.KestrelTests
"Hello World!");
}
}
}
}
[ConditionalFact]
[FrameworkSkipCondition(RuntimeFrameworks.Mono, SkipReason = "Test hangs after execution on Mono.")]
public async Task ThrowingSynchronousConnectionFilterDoesNotCrashServer()
{
var serviceContext = new TestServiceContext()
{
ConnectionFilter = new ThrowingConnectionFilter()
};
using (var server = new TestServer(App, serviceContext))
{
using (var connection = new TestConnection())
{
try
{
await connection.SendEnd(
"POST / HTTP/1.0",
"",
"Hello World?");
}
catch (IOException)
{
// Will throw because the exception in the connection filter will close the connection.
Assert.True(true);
}
}
}
}
private class RewritingConnectionFilter : IConnectionFilter
{
@ -112,6 +142,14 @@ namespace Microsoft.AspNet.Server.KestrelTests
}
}
private class ThrowingConnectionFilter : IConnectionFilter
{
public Task OnConnection(ConnectionFilterContext context)
{
throw new Exception();
}
}
private class RewritingStream : Stream
{
private readonly Stream _innerStream;