dotnet / dotnet/winforms

Race condition in ImageCodecInfoHelper

Open
#14,884 2 comments 0 reactions 1 assignee Claimed by @KlausLoeffelmann View on GitHub
untriaged
Dominant language
C#
Stars
4.9k
Forks
1.1k
Avg merge
1d 13m
Merged PRs (30d)
85

Description

### Description

When 2 threads try to save a bitmap via Image.Save(Stream, ImageFormat), one of the two threads fails with a
System.ArgumentNullException : Value cannot be null. (Parameter 'encoder')

The reason for this is an allocated s_encoders static field on ImageCodecInfoHelper, but it has no values in the array yet.
See this image where the array is created and assigned to s_encoders but populated later.
The array should be created and assigned to a temporary variable and when all array elements have been set assigned to s_encoders
Image

### Reproduction Steps

Run the following repeatedly and it will raise an Exception once in a while.

void Main()
{
var bitmaps = new List();
for (var i = 0; i < 10; i++)
{
bitmaps.Add(new Bitmap(100, 100));
}

Parallel.ForEach(bitmaps, bitmap =>
{
using var stream = new MemoryStream();
bitmap.Save(stream, ImageFormat.Png);
});

foreach (var bitmap in bitmaps)
{
bitmap.Dispose();
}
}

### Expected behavior

s_encoders should have a proper value for every element in it.

### Actual behavior

s_encoders can be returned in thread B, while thread A is still busy populating its items

### Regression?

_No response_

### Known Workarounds

In our example we can workaround it by creating a Bitmap and saving it to a dummy stream once,
This guarantees the s_encoders is being populated properly.

### Configuration

_No response_

### Other information

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.