From 854ea5d0962921a8f1831376f77b1bef8a57b75a Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 21 Feb 2022 23:25:22 +0100 Subject: [PATCH] workaround for #2001 / https://github.com/dotnet/runtime/issues/65466 --- .../UniformUnmanagedMemoryPoolMemoryAllocator.cs | 13 +++++++++++-- .../UniformUnmanagedPoolMemoryAllocatorTests.cs | 13 +++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/ImageSharp/Memory/Allocators/UniformUnmanagedMemoryPoolMemoryAllocator.cs b/src/ImageSharp/Memory/Allocators/UniformUnmanagedMemoryPoolMemoryAllocator.cs index 16a3cb73d1..5f591a9bb3 100644 --- a/src/ImageSharp/Memory/Allocators/UniformUnmanagedMemoryPoolMemoryAllocator.cs +++ b/src/ImageSharp/Memory/Allocators/UniformUnmanagedMemoryPoolMemoryAllocator.cs @@ -74,6 +74,10 @@ namespace SixLabors.ImageSharp.Memory this.nonPoolAllocator = new UnmanagedMemoryAllocator(unmanagedBufferSizeInBytes); } + // This delegate allows overriding the method returning the available system memory, + // so we can test our workaround for https://github.com/dotnet/runtime/issues/65466 + internal static Func GetTotalAvailableMemoryBytes { get; set; } = () => GC.GetGCMemoryInfo().TotalAvailableMemoryBytes; + /// protected internal override int GetBufferCapacityInBytes() => this.poolBufferSizeInBytes; @@ -152,8 +156,13 @@ namespace SixLabors.ImageSharp.Memory // https://github.com/dotnet/runtime/issues/55126#issuecomment-876779327 if (Environment.Is64BitProcess || !RuntimeInformation.FrameworkDescription.StartsWith(".NET 5.0")) { - GCMemoryInfo info = GC.GetGCMemoryInfo(); - return info.TotalAvailableMemoryBytes / 8; + long total = GetTotalAvailableMemoryBytes(); + + // Workaround for https://github.com/dotnet/runtime/issues/65466 + if (total > 0) + { + return total / 8; + } } #endif diff --git a/tests/ImageSharp.Tests/Memory/Allocators/UniformUnmanagedPoolMemoryAllocatorTests.cs b/tests/ImageSharp.Tests/Memory/Allocators/UniformUnmanagedPoolMemoryAllocatorTests.cs index 45a7cc278e..0c59e334c5 100644 --- a/tests/ImageSharp.Tests/Memory/Allocators/UniformUnmanagedPoolMemoryAllocatorTests.cs +++ b/tests/ImageSharp.Tests/Memory/Allocators/UniformUnmanagedPoolMemoryAllocatorTests.cs @@ -379,5 +379,18 @@ namespace SixLabors.ImageSharp.Tests.Memory.Allocators g1.GetSpan()[0] = 42; } } + + [Fact] + public void Issue2001_NegativeMemoryReportedByGc() + { + RemoteExecutor.Invoke(RunTest).Dispose(); + + static void RunTest() + { + // Emulate GC.GetGCMemoryInfo() issue https://github.com/dotnet/runtime/issues/65466 + UniformUnmanagedMemoryPoolMemoryAllocator.GetTotalAvailableMemoryBytes = () => -402354176; + _ = MemoryAllocator.Create(); + } + } } }