Skip to content

Memory leak in PNG decoder #2080

@miere43

Description

@miere43

Prerequisites

  • I have written a descriptive issue title
  • I have verified that I am running the latest version of ImageSharp
  • I have verified if the problem exist in both DEBUG and RELEASE mode
  • I have searched open and closed issues to ensure it has not already been reported

ImageSharp version

2.1.0

Other ImageSharp packages and versions

None

Environment (Operating system, version and so on)

Windows 10 Pro, version 21H1, OS build 19043.1586

.NET Framework version

6.0.3

Description

Using Image.Load with PNG image leaks memory after calling Dispose on that image.

Steps to Reproduce

Code for reproduction:

using System.Diagnostics;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Diagnostics;

MemoryDiagnostics.UndisposedAllocation += stackTrace =>
{
    // This callback is never called for some reason.
    Console.WriteLine(stackTrace);
    Debugger.Break();
};

static void Test()
{
    using var stream = File.OpenRead("C:\image.png");
    using var image = Image.Load(stream);
}

Test();

Console.WriteLine($"Leaks: {MemoryDiagnostics.TotalUndisposedAllocationCount}");
Console.ReadLine();

Program output:

Leaks: 1

UndisposedAllocation callback doesn't work for some reason, this is one of stack traces from my project:

   at System.Environment.get_StackTrace()
   at SixLabors.ImageSharp.Memory.Internals.SharedArrayPoolBuffer`1..ctor(Int32 lengthInElements)
   at SixLabors.ImageSharp.Memory.UniformUnmanagedMemoryPoolMemoryAllocator.Allocate[T](Int32 length, AllocationOptions options)
   at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.TryReadChunk(PngChunk& chunk)
   at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.ReadNextDataChunk()
   at SixLabors.ImageSharp.Compression.Zlib.ZlibInflateStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at System.IO.Compression.DeflateStream.ReadCore(Span`1 buffer)
   at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.DecodePixelData[TPixel](DeflateStream compressedStream, ImageFrame`1 image, PngMetadata pngMetadata)
   at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.ReadScanlines[TPixel](PngChunk chunk, ImageFrame`1 image, PngMetadata pngMetadata)
   at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.Decode[TPixel](BufferedReadStream stream, CancellationToken cancellationToken)
   at SixLabors.ImageSharp.Formats.ImageDecoderUtilities.Decode[TPixel](IImageDecoderInternals decoder, Configuration configuration, Stream stream, Func`3 largeImageExceptionFactory, CancellationToken cancellationToken)
   at SixLabors.ImageSharp.Formats.ImageDecoderUtilities.Decode[TPixel](IImageDecoderInternals decoder, Configuration configuration, Stream stream, CancellationToken cancellationToken)
   at SixLabors.ImageSharp.Formats.Png.PngDecoder.Decode[TPixel](Configuration configuration, Stream stream, CancellationToken cancellationToken)
   at SixLabors.ImageSharp.Formats.Png.PngDecoder.Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken)
   at SixLabors.ImageSharp.Image.Decode(Stream stream, Configuration config, CancellationToken cancellationToken)
   at SixLabors.ImageSharp.Image.<>c__DisplayClass131_0.<LoadWithFormatAsync>b__0(Stream s, CancellationToken ct)
   at SixLabors.ImageSharp.Image.WithSeekableStreamAsync[T](Configuration configuration, Stream stream, Func`3 action, CancellationToken cancellationToken)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.ExecutionContextCallback(Object s)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext(Thread threadPoolThread)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext()
   at System.Runtime.CompilerServices.TaskAwaiter.<>c.<OutputWaitEtwEvents>b__12_0(Action innerContinuation, Task innerTask)
   at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(Action action, Boolean allowInlining)
   at System.Threading.Tasks.Task.RunContinuations(Object continuationObject)
   at System.Threading.Tasks.Task`1.TrySetResult(TResult result)
   at System.IO.Stream.<CopyToAsync>g__Core|29_0(Stream source, Stream destination, Int32 bufferSize, CancellationToken cancellationToken)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext(Thread threadPoolThread)
   at System.Runtime.CompilerServices.TaskAwaiter.<>c.<OutputWaitEtwEvents>b__12_0(Action innerContinuation, Task innerTask)
   at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(Action action, Boolean allowInlining)
   at System.Threading.Tasks.Task.RunContinuations(Object continuationObject)
   at System.Threading.Tasks.Task.FinishSlow(Boolean userDelegateExecute)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
   at System.Threading.Thread.StartCallback()

Images

image.png

image

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions