Skip to content

A bug in FileStream (async + buffer) since .Net 6? #80344

Closed
@yeunglee

Description

@yeunglee

Description

I encounter a strange issue in FileStream. I provide the code and test data in https://github.com/yeunglee/file_stream_test

The major issue is that (async random read + special buffer size + special file) in FileStream encounters unexpected read.

Here is a simple code. The full code can be retrieved from https://github.com/yeunglee/file_stream_test

const string FILE_PATH = "test_data";

// SOLUTION #1: change buffer size. for example: 1024, 4096, 1024 * 512 - 1, 1024 * 512 + 1
const int FILE_BUFFER_SIZE = 1024 * 512;

Console.WriteLine($".Net version: {Environment.Version}");
Console.WriteLine($"OS version: {Environment.OSVersion}");

var fileData = await File.ReadAllBytesAsync(FILE_PATH);
// SOLUTION #2: add FileOptions.RandomAccess
await using var fs = new FileStream(FILE_PATH, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, FILE_BUFFER_SIZE, FileOptions.Asynchronous);

void SetPosition(long p) => fs.Position = p;

async Task ReadAsync(int size)
{
    var initialPosition = fs.Position;
    var content = new byte[size];

    // SOLUTION #3: use sync Read instead of async ReadAsync
    var count = await fs.ReadAsync(content, 0, content.Length);

    var isMatched = fileData.Skip((int)initialPosition).Take(count).SequenceEqual(content.Take(count));

    if (!isMatched)
    {
        Console.WriteLine($"!!!Content is inconsistent!!! position={initialPosition:#,0} size={size:#,0} count={count:#,0}");
        Environment.Exit(1);
    }
}

await ReadAsync(1);
await ReadAsync(4);
await ReadAsync(4);
await ReadAsync(118);
await ReadAsync(4);
await ReadAsync(524288);
SetPosition(524377);
await ReadAsync(524288);
SetPosition(1048633);
await ReadAsync(524288);
SetPosition(1572864);
await ReadAsync(524288);
await ReadAsync(524288);
SetPosition(2621431);
await ReadAsync(524288);

Reproduction Steps

  1. Checkout the demo code from https://github.com/yeunglee/file_stream_test
  2. Execute dotnet run (The dotnet project file specify .Net 6, you can change .Net version)
  3. Check the execution result from step#2.

Expected behavior

The demo program outputs:
FileStream is good

Actual behavior

The demo program outputs:
!!!Content is inconsistent!!! position=2,621,431 size=524,288 count=326,069

Regression?

.Net 3.1 and .Net 5 are fine.

Known Workarounds

There are three four workarounds:

  1. Change file buffer size
  2. Or change file option (add FileOptions.RandomAccess)
  3. Or use sync Read instead of async ReadAsync

The workaround ways are commented in demo program code.

  1. The demo code is fine with .Net 5, .Net 3.1

Configuration

This issue can be reproduced in

  1. WinServer 2022 (21H2) (x64)+ .Net 6.0.3
  2. Win11 Enterprise (22H2) (x64) + .Net 7.0.1
  3. Win11 Enterprise (22H2) (x64) + .Net 6.0.12
  4. Win10 LTSC (1809) (x64) + .Net 6.0.11

Both Debug and Release configuration are same result.

Other information

No response

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions