-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Calling Pipe.Writer.WriteAsync after Pipe.Writer.Advance flush truncated data to the PipeReader. #62167
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
It should not be possible for runtime/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/PipeReader.cs Lines 61 to 64 in 7a62468
Is it possible that you're using a |
I'm using the duplex "Pipe" implementation. [Test]
public async Task ReadAtLeastAsync_works()
{
Pipe pipe = new Pipe(new PipeOptions(minimumSegmentSize: 1));
Task<ReadResult> resTask = pipe.Reader.ReadAtLeastAsync( 26 ).AsTask();
pipe.Writer.GetSpan( 14 );
pipe.Writer.Advance( 14 );
await pipe.Writer.WriteAsync( new byte[12] );
ReadResult res = await resTask;
res.Buffer.Length.Should().Be( 26 ); //fails
} Can I also do the PR to fixes this bug, if possible ? |
Looks like the bug is worst than I thought; [Test]
public async Task ReadAtLeastAsync_works()
{
Memory<byte> buffer = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 };
Pipe pipe = new( new PipeOptions( minimumSegmentSize: 1 ) );
Task<ReadResult> resTask = pipe.Reader.ReadAtLeastAsync( 26 ).AsTask();
var mem = pipe.Writer.GetMemory( 14 )[..14];
buffer.CopyTo( mem );
pipe.Writer.Advance( 14 );
await pipe.Writer.WriteAsync( new byte[12] { 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 } );
ReadResult res = await resTask;
Console.WriteLine( string.Join( ", ", res.Buffer.ToArray() ) );
res.Buffer.Length.Should().Be( 26 );
} Output: It looks like it's a regression from 4.5.4(pass test) from to 5.0.0(fail test). I'm feeling that I should not This bug (if this is indeed a bug and not missing docs) is not exclusive to |
…nts if called after an .Advance(int)
I went ahead and made a PR because the fix is one line. |
… called after an .Advance(int) (#62306)
… called after an .Advance(int)
… called after an .Advance(int)
…ter .Advance(int) (#62348) * Fixes #62167. WriteAsync was bugged when writing multiple segments if called after an .Advance(int) * Add packaging changes to IO Pipelines Co-authored-by: Kuinox <[email protected]> Co-authored-by: Santiago Fernandez Madero <[email protected]>
…ter .Advance(int) (#62350) * Fixes #62167. WriteAsync was bugged when writing multiple segments if called after an .Advance(int) * Add packaging changes Co-authored-by: Kuinox <[email protected]> Co-authored-by: Santiago Fernandez Madero <[email protected]>
Description
(I edited this issue when I noticed the bug did not affected only ReadAtLeastAsync, original title was 'Pipe.ReadAtLeastAsync return with less bytes than asked.')
Calling Pipe.Writer.WriteAsync after Pipe.Writer.Advance flush truncated data to the PipeReader.
I initially found this bug because ReadAtLeastAsync returned me a 12 bytes buffer, when I asked for 26.
Reproduction Steps
Edit:
Expected behavior
Data written is not overwritten.
Actual behavior
Only 12 bytes are returned. The first write is partially overwritten.
Regression?
The reproduction does not show the bug on version 4.5.4.
Known Workarounds
Call FlushAsync before calling WriteAsync if you did Advance() before.
Configuration
N/A.
The text was updated successfully, but these errors were encountered: