Skip to content
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

Potential ValueTask-related issues in Kestrel #16876

Closed
stephentoub opened this issue Nov 6, 2019 · 3 comments · Fixed by #31221
Closed

Potential ValueTask-related issues in Kestrel #16876

stephentoub opened this issue Nov 6, 2019 · 3 comments · Fixed by #31221
Assignees
Labels
affected-very-few This issue impacts very few customers area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions feature-kestrel Perf severity-nice-to-have This label is used by an internal tool task
Milestone

Comments

@stephentoub
Copy link
Member

stephentoub commented Nov 6, 2019

I haven't fully investigated all of these, just enough to see that there might be an issue to be followed up on...

  1. Ignored results:

https://github.com/aspnet/AspNetCore/blob/6a6deb298c8b3385213174dd023a45f6a309da5f/src/Servers/Kestrel/Core/src/Internal/Http2/FlowControl/StreamInputFlowControl.cs#L55

https://github.com/aspnet/AspNetCore/blob/6a6deb298c8b3385213174dd023a45f6a309da5f/src/Servers/Kestrel/Core/src/Internal/Http2/FlowControl/StreamInputFlowControl.cs#L88

https://github.com/aspnet/AspNetCore/blob/6a6deb298c8b3385213174dd023a45f6a309da5f/src/Servers/Kestrel/Core/src/Internal/Http2/Http2Connection.cs#L144

https://github.com/aspnet/AspNetCore/blob/6a6deb298c8b3385213174dd023a45f6a309da5f/src/Servers/Kestrel/Core/src/Internal/Http2/Http2Connection.cs#L1053

https://github.com/aspnet/AspNetCore/blob/6a6deb298c8b3385213174dd023a45f6a309da5f/src/Servers/Kestrel/Core/src/Internal/Http2/Http2Connection.cs#L1063

https://github.com/aspnet/AspNetCore/blob/3ecdc403189a28e2f36723663f50e58c4637e3aa/src/Servers/Kestrel/Core/src/Internal/Http2/Http2Stream.cs#L103

https://github.com/aspnet/AspNetCore/blob/3ecdc403189a28e2f36723663f50e58c4637e3aa/src/Servers/Kestrel/Core/src/Internal/Http2/Http2Stream.cs#L470

These are calling a ValueTask-returning method and ignoring the result. If the ValueTask is backed by something that's pooled, not awaiting it could result in that pooled object getting thrown away.

  1. Semi-ignored result, and potential reuse:

https://github.com/aspnet/AspNetCore/blob/6a6deb298c8b3385213174dd023a45f6a309da5f/src/Servers/Kestrel/Core/src/Internal/Http2/Http2OutputProducer.cs#L67

This is storing a ValueTask into a field, which is then returned from every call to WriteStreamSuffixAsync:

https://github.com/aspnet/AspNetCore/blob/6a6deb298c8b3385213174dd023a45f6a309da5f/src/Servers/Kestrel/Core/src/Internal/Http2/Http2OutputProducer.cs#L207-L221

Same for HTTP/1.1:

https://github.com/aspnet/AspNetCore/blob/caa910ceeba5f2b2c02c47a23ead0ca31caea6f0/src/Servers/Kestrel/Core/src/Internal/Http/Http1OutputProducer.cs#L122

That in turn is used in WriteSuffix:

https://github.com/aspnet/AspNetCore/blob/3ecdc403189a28e2f36723663f50e58c4637e3aa/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.cs#L1053-L1058

Two potential issues with that: a) if it's already completed successfully we never call GetAwaiter().GetResult() on it which means if it's pooled it won't be returned, and b) if it wasn't completed and we await it, then if it's used again we're going to be reusing an already consumed instance.

  1. Attempting to synchronously block on a ValueTask

https://github.com/aspnet/AspNetCore/blob/caa910ceeba5f2b2c02c47a23ead0ca31caea6f0/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.cs#L927

a) Synchronous blocking in ASP.NET?
b) Such use isn't supported on ValueTasks. It may happen to work today based on how the ValueTask was created, but it's in no way guaranteed to.

https://github.com/aspnet/AspNetCore/blob/caa910ceeba5f2b2c02c47a23ead0ca31caea6f0/src/Servers/Kestrel/Core/src/Middleware/Internal/DuplexPipeStream.cs#L69-L74

This one is similar. The comment talks about using Result being ok because it calls GetAwaiter().GetResult(), but GetAwaiter().GetResult() isn't guaranteed to block. It'll work ok if the implementation is backed by a value or a Task, but if it's backed by an IValueTaskSource, all bets are off.

cc: @davidfowl

@GrabYourPitchforks
Copy link
Member

The "ignored result" presumably should be easy enough to catch via an analyzer. Would an analyzer have caught the other potential misuses? Should we see this as a forcing function for us to write such an analyzer?

@stephentoub
Copy link
Member Author

stephentoub commented Nov 6, 2019

These are all from an analyzer 😉
dotnet/roslyn-analyzers#3001

@davidfowl
Copy link
Member

a) Synchronous blocking in ASP.NET?

HAH, yes, we never fixed the expect 100 continue code path.

@jkotalik jkotalik added this to the 5.0.0-preview1 milestone Nov 13, 2019
@analogrelay analogrelay removed this from the 5.0.0-preview1 milestone Mar 11, 2020
@shirhatti shirhatti added this to the Next sprint planning milestone Mar 25, 2020
@BrennanConroy BrennanConroy added affected-very-few This issue impacts very few customers severity-nice-to-have This label is used by an internal tool task labels Nov 6, 2020 — with ASP.NET Core Issue Ranking
@stephentoub stephentoub assigned stephentoub and unassigned halter73 Mar 24, 2021
@ghost ghost locked as resolved and limited conversation to collaborators Apr 29, 2021
@amcasey amcasey added area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions and removed area-runtime labels Jun 2, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
affected-very-few This issue impacts very few customers area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions feature-kestrel Perf severity-nice-to-have This label is used by an internal tool task
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants