Skip to content

System.IO.Pipelines inifinite wait PipeReader.ReadAtLeastAsync(Int32, CancellationToken) #66645

@eagleoriginal

Description

@eagleoriginal

Description

Infinite wait. OperationCanceledException was not throwed as expected if only part of required length has been readen from stream.
In example actually has 12 bytes for read, but syntetical code ReadAtLeastAsync wait for 30 bytes. So it leads to infinite wait ignoring cancelation token.

Reproduction Steps

using System.IO.Pipelines;
var cts = new CancellationTokenSource(3000);
var pipe = new Pipe(PipeOptions.Default);
var bytes = new byte[12];
await pipe.Writer.WriteAsync(bytes).ConfigureAwait(false);

var result = await pipe.Reader.ReadAtLeastAsync(30, cts.Token).ConfigureAwait(false);
pipe.Reader.AdvanceTo(result.Buffer.GetPosition(30));
Console.WriteLine("Stage 1");

Expected behavior

Expected getting: System.OperationCanceledException: The operation was canceled.

Actual behavior

Infinitie wait.....

Known Workarounds

Using this code from Microsoft sources avoid infinite wait:

protected static async ValueTask<ReadResult> ReadAtLeastAsyncCore(PipeReader reader, int minimumSize, CancellationToken cancellationToken)
        {
            while (true)
            {
                var result = await reader.ReadAsync(cancellationToken).ConfigureAwait(false);
                var buffer = result.Buffer;

                if (buffer.Length >= minimumSize || result.IsCompleted || result.IsCanceled)
                {
                    return result;
                }

                // Keep buffering until we get more data
                reader.AdvanceTo(buffer.Start, buffer.End);
            }
        }

Configuration

.net 6.0
System.IO.Pipelines v6.0.2

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions