diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Http/Connection.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Http/Connection.cs index 9c9e225a9f..d48bc08944 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Http/Connection.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Http/Connection.cs @@ -171,7 +171,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http // Called on Libuv thread public void Tick(long timestamp) { - if (timestamp > Interlocked.Read(ref _timeoutTimestamp)) + if (timestamp > PlatformApis.VolatileRead(ref _timeoutTimestamp)) { ConnectionControl.CancelTimeout(); diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Http/DateHeaderValueManager.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Http/DateHeaderValueManager.cs index b824fb606d..cb36c22d34 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Http/DateHeaderValueManager.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Http/DateHeaderValueManager.cs @@ -6,6 +6,7 @@ using System.Text; using System.Threading; using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure; using Microsoft.Net.Http.Headers; +using Microsoft.AspNetCore.Server.Kestrel.Internal.Networking; namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http { @@ -158,7 +159,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http } // No requests since the last timer tick, we need to check if we're beyond the idle threshold - if ((now.Ticks - Interlocked.Read(ref _lastRequestSeenTicks)) >= _timeWithoutRequestsUntilIdle.Ticks) + if ((now.Ticks - PlatformApis.VolatileRead(ref _lastRequestSeenTicks)) >= _timeWithoutRequestsUntilIdle.Ticks) { // No requests since idle threshold so stop the timer if it's still running StopTimer(); diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Networking/PlatformApis.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Networking/PlatformApis.cs index e81974adb2..6cd2341815 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Networking/PlatformApis.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Networking/PlatformApis.cs @@ -1,7 +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. +using System; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Threading; namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Networking { @@ -16,5 +19,19 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Networking public static bool IsWindows { get; } public static bool IsDarwin { get; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long VolatileRead(ref long value) + { + if (IntPtr.Size == 8) + { + return Volatile.Read(ref value); + } + else + { + // Avoid torn long reads on 32-bit + return Interlocked.Read(ref value); + } + } } }