From 8e57b5e3b61ec72b190461def0464b225ffa1a04 Mon Sep 17 00:00:00 2001 From: Brennan Conroy Date: Thu, 10 Dec 2020 00:19:53 +0000 Subject: [PATCH] Merged PR 11157: Run callbacks outside of locks --- .../Internal/Infrastructure/TimeoutControl.cs | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/Servers/Kestrel/Core/src/Internal/Infrastructure/TimeoutControl.cs b/src/Servers/Kestrel/Core/src/Internal/Infrastructure/TimeoutControl.cs index 1d9cef950a..79f74e376d 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Infrastructure/TimeoutControl.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Infrastructure/TimeoutControl.cs @@ -89,6 +89,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure return; } + var timeout = false; + lock (_readTimingLock) { if (!_readTimingEnabled) @@ -105,10 +107,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure var elapsedSeconds = (double)_readTimingElapsedTicks / TimeSpan.TicksPerSecond; var rate = _readTimingBytesRead / elapsedSeconds; - if (rate < _minReadRate.BytesPerSecond && !Debugger.IsAttached) - { - _timeoutHandler.OnTimeout(TimeoutReason.ReadDataRate); - } + timeout = rate < _minReadRate.BytesPerSecond && !Debugger.IsAttached; } // PauseTimingReads() cannot just set _timingReads to false. It needs to go through at least one tick @@ -120,10 +119,18 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure _readTimingPauseRequested = false; } } + + if (timeout) + { + // Run callbacks outside of the lock + _timeoutHandler.OnTimeout(TimeoutReason.ReadDataRate); + } } private void CheckForWriteDataRateTimeout(long timestamp) { + var timeout = false; + lock (_writeTimingLock) { // Assume overly long tick intervals are the result of server resource starvation. @@ -135,10 +142,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure _writeTimingTimeoutTimestamp += extraTimeForTick; } - if (_concurrentAwaitingWrites > 0 && timestamp > _writeTimingTimeoutTimestamp && !Debugger.IsAttached) - { - _timeoutHandler.OnTimeout(TimeoutReason.WriteDataRate); - } + timeout = _concurrentAwaitingWrites > 0 && timestamp > _writeTimingTimeoutTimestamp && !Debugger.IsAttached; + } + + if (timeout) + { + // Run callbacks outside of the lock + _timeoutHandler.OnTimeout(TimeoutReason.WriteDataRate); } }