Skip to content

Possible false positive memory leak reports in tests #2178

@br3aker

Description

@br3aker

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

main branch

Other ImageSharp packages and versions

None

Environment (Operating system, version and so on)

Windows 10

.NET Framework version

net6

Description

We have TestFile class for testing purposes. It works as a cache of some sort and has this line:

private Image<Rgba32> Image => this.image ?? (this.image = ImageSharp.Image.Load<Rgba32>(this.Bytes));

I think this is responsible for random false positive memory leaks in tests, e.g. what happens in this case if memory leaks diagnostics are on and if we would imagine this is the only test in out test suite?

// TestFile instance is injected by test attributes
// Doesn't really matter in this example
[Theory]
public void Test(TestFile testFile)
{
    // testFile.CreateRgba32Image() creates 2 Image<Rgba32> objects
    // one is lazily initialized and stored in cache and one is created via Clone() call
    // and used in this test
    using (var image = testFile.CreateRgba32Image())
    {
        // Undisposed objects count should be 2 here
        this.Output.WriteLine(image.Size());
    }
    // Cloned image is disposed and TestFile instance image is not disposed
    // Thus undisposed count should be 1 here which can lead to false positive memory leak
}

And aren't these lines in TestFile.cs:

public byte[] Bytes => this.bytes ?? (this.bytes = File.ReadAllBytes(this.FullPath));

private Image<Rgba32> Image => this.image ?? (this.image = ImageSharp.Image.Load<Rgba32>(this.Bytes));

not thread safe?

File.ReadAllBytes(this.FullPath) can be called by multiple threads and won't leak as it returns managed array.
this.image = ImageSharp.Image.Load<Rgba32>(this.Bytes) can also be called by multiple threads but extra instance would just leak.

Steps to Reproduce

This happens quite randomly so there's no 100% correct steps to reproduce it.

Images

No response

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