Skip to content

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

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions