Do not enforce timeouts when the debugger is attached
This commit is contained in:
parent
3fcd909d90
commit
9b4be69e9d
|
|
@ -44,6 +44,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
|
||||
// For testing
|
||||
internal Frame Frame => _frame;
|
||||
internal IDebugger Debugger { get; set; } = DebuggerWrapper.Singleton;
|
||||
|
||||
|
||||
public bool TimedOut { get; private set; }
|
||||
|
||||
|
|
@ -263,14 +265,17 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
// TODO: Use PlatformApis.VolatileRead equivalent again
|
||||
if (timestamp > Interlocked.Read(ref _timeoutTimestamp))
|
||||
{
|
||||
CancelTimeout();
|
||||
|
||||
if (_timeoutAction == TimeoutAction.SendTimeoutResponse)
|
||||
if (!Debugger.IsAttached)
|
||||
{
|
||||
SetTimeoutResponse();
|
||||
}
|
||||
CancelTimeout();
|
||||
|
||||
Timeout();
|
||||
if (_timeoutAction == TimeoutAction.SendTimeoutResponse)
|
||||
{
|
||||
SetTimeoutResponse();
|
||||
}
|
||||
|
||||
Timeout();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -285,7 +290,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
var elapsedSeconds = (double)_readTimingElapsedTicks / TimeSpan.TicksPerSecond;
|
||||
var rate = Interlocked.Read(ref _readTimingBytesRead) / elapsedSeconds;
|
||||
|
||||
if (rate < _frame.RequestBodyMinimumDataRate.Rate)
|
||||
if (rate < _frame.RequestBodyMinimumDataRate.Rate && !Debugger.IsAttached)
|
||||
{
|
||||
Log.RequestBodyMininumDataRateNotSatisfied(_context.ConnectionId, _frame.TraceIdentifier, _frame.RequestBodyMinimumDataRate.Rate);
|
||||
Timeout();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Internal.System.IO.Pipelines;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
// 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.Diagnostics;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
||||
{
|
||||
internal sealed class DebuggerWrapper : IDebugger
|
||||
{
|
||||
private DebuggerWrapper()
|
||||
{ }
|
||||
|
||||
public static IDebugger Singleton { get; } = new DebuggerWrapper();
|
||||
|
||||
public bool IsAttached => Debugger.IsAttached;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
||||
{
|
||||
public interface IDebugger
|
||||
{
|
||||
bool IsAttached { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -50,19 +50,60 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
_pipeFactory.Dispose();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DoesNotTimeOutWhenDebuggerIsAttached()
|
||||
{
|
||||
var mockDebugger = new Mock<IDebugger>();
|
||||
mockDebugger.SetupGet(g => g.IsAttached).Returns(true);
|
||||
_frameConnection.Debugger = mockDebugger.Object;
|
||||
_frameConnection.CreateFrame(new DummyApplication(), _frameConnectionContext.Input.Reader, _frameConnectionContext.Output);
|
||||
|
||||
var now = DateTimeOffset.Now;
|
||||
_frameConnection.Tick(now);
|
||||
_frameConnection.SetTimeout(1, TimeoutAction.SendTimeoutResponse);
|
||||
_frameConnection.Tick(now.AddTicks(2).Add(Heartbeat.Interval));
|
||||
|
||||
Assert.False(_frameConnection.TimedOut);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DoesNotTimeOutWhenRequestBodyDoesNotSatisfyMinimumDataRateButDebuggerIsAttached()
|
||||
{
|
||||
var mockDebugger = new Mock<IDebugger>();
|
||||
mockDebugger.SetupGet(g => g.IsAttached).Returns(true);
|
||||
_frameConnection.Debugger = mockDebugger.Object;
|
||||
var requestBodyMinimumDataRate = 100;
|
||||
var mockLogger = new Mock<IKestrelTrace>();
|
||||
mockLogger.Setup(l => l.RequestBodyMininumDataRateNotSatisfied(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<double>())).Throws(new InvalidOperationException("Should not log"));
|
||||
|
||||
TickBodyWithMinimumDataRate(mockLogger.Object, requestBodyMinimumDataRate);
|
||||
|
||||
Assert.False(_frameConnection.TimedOut);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TimesOutWhenRequestBodyDoesNotSatisfyMinimumDataRate()
|
||||
{
|
||||
var requestBodyMinimumDataRate = 100;
|
||||
var mockLogger = new Mock<IKestrelTrace>();
|
||||
TickBodyWithMinimumDataRate(mockLogger.Object, requestBodyMinimumDataRate);
|
||||
|
||||
// Timed out
|
||||
Assert.True(_frameConnection.TimedOut);
|
||||
mockLogger.Verify(logger =>
|
||||
logger.RequestBodyMininumDataRateNotSatisfied(It.IsAny<string>(), It.IsAny<string>(), requestBodyMinimumDataRate), Times.Once);
|
||||
}
|
||||
|
||||
private void TickBodyWithMinimumDataRate(IKestrelTrace logger, int requestBodyMinimumDataRate)
|
||||
{
|
||||
var requestBodyGracePeriod = TimeSpan.FromSeconds(5);
|
||||
|
||||
_frameConnectionContext.ServiceContext.ServerOptions.Limits.RequestBodyMinimumDataRate =
|
||||
new MinimumDataRate(rate: requestBodyMinimumDataRate, gracePeriod: requestBodyGracePeriod);
|
||||
|
||||
var mockLogger = new Mock<IKestrelTrace>();
|
||||
_frameConnectionContext.ServiceContext.Log = mockLogger.Object;
|
||||
_frameConnectionContext.ServiceContext.Log = logger;
|
||||
|
||||
_frameConnection.CreateFrame(new DummyApplication(context => Task.CompletedTask), _frameConnectionContext.Input.Reader, _frameConnectionContext.Output);
|
||||
_frameConnection.CreateFrame(new DummyApplication(), _frameConnectionContext.Input.Reader, _frameConnectionContext.Output);
|
||||
_frameConnection.Frame.Reset();
|
||||
|
||||
// Initialize timestamp
|
||||
|
|
@ -75,11 +116,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
now += requestBodyGracePeriod + TimeSpan.FromSeconds(1);
|
||||
_frameConnection.BytesRead(1);
|
||||
_frameConnection.Tick(now);
|
||||
|
||||
// Timed out
|
||||
Assert.True(_frameConnection.TimedOut);
|
||||
mockLogger.Verify(logger =>
|
||||
logger.RequestBodyMininumDataRateNotSatisfied(It.IsAny<string>(), It.IsAny<string>(), requestBodyMinimumDataRate), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -14,6 +14,11 @@ namespace Microsoft.AspNetCore.Testing
|
|||
private readonly RequestDelegate _requestDelegate;
|
||||
private readonly IHttpContextFactory _httpContextFactory;
|
||||
|
||||
public DummyApplication()
|
||||
: this(_ => Task.CompletedTask)
|
||||
{
|
||||
}
|
||||
|
||||
public DummyApplication(RequestDelegate requestDelegate)
|
||||
: this(requestDelegate, null)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue