Skip to content

Remove dependency on pipe events in HttpConnection #11132

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

Merged
merged 3 commits into from
Jun 13, 2019

Conversation

davidfowl
Copy link
Member

  • Refactored the HttpConnection to not depend on OnReaderCompleted and OnWriterCompleted. Instead we use ConnectionClosed to detect the FIN that we propagate via ConnectedAborted.
  • Fire ConnectionClosed when a FIN is received from both transports.
  • Remove pipe completion from Http1Connection and Http1OutputProducer. Instead just return from request processing.
  • Flow the CancellaitonToken property in RawStream

- Refactored the HttpConnection to not depend on OnReaderCompleted and OnWriterCompleted. Instead we use ConnectionClosed to detect the FIN that we propagate via ConnectedAborted.
- Fire ConnectionClosed when a FIN is received from both transports.
- Remove pipe completion from Http1Connection and Http1OutputProducer. Instead just return from request processing.
- Flow the CancellaitonToken property in RawStream
@analogrelay analogrelay removed their request for review June 12, 2019 14:41
@jkotalik
Copy link
Contributor

I'd also prefer to have this for #11109

Copy link
Contributor

@jkotalik jkotalik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change itself seems good, but I think we should go over this in person before merging. Also to figure out how we can sync this with https://github.com/aspnet/AspNetCore/pull/11109/checks?check_run_id=146487478. I'd rather merge this first before merging my PR as I don't want to have the pipe scheduler be thread pool.

@analogrelay analogrelay added this to the 3.0.0-preview7 milestone Jun 12, 2019
- Cancel the transport input on RawStream to yield the pending read. This is much more efficient than passing a cancellation token into everything (and more reliable)
- Fixed the RequestTests to not depend on inline scheduling
- Properly dispose things in the LibuvOutputConsumerTests
@@ -187,6 +173,10 @@ private async Task DoReceive()
{
// If Shutdown() has already bee called, assume that was the reason ProcessReceives() exited.
Input.Complete(_shutdownReason ?? error);

FireConnectionClosed();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes me wish we called to ConnectionClosed token FinReceived or something like that, because the connection might be only half closed at this point.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could argue the same about HttpContext.ConnectionAborted, I don't think it makes a difference.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You absolutely could, but at least that's HTTP-specific so it makes a bit more sense.

private void FireConnectionClosed()
{
// Guard against scheduling this multiple times
if (_connectionClosed)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see you're taking advantage of the single-threaded nature of libuv's event loop 👍

// Fire the connection closed token and wait for it to complete
var waitForConnectionClosedTcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
// Ensure this always fires
FireConnectionClosed();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're going to continue firing ConnectionClosed for libuv output errors, we should do the same for the socket transport.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean? Aren't we doing that? It always fires no?

Copy link
Member

@halter73 halter73 Jun 13, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm now thinking about making this more like the socket transport instead. The important thing is consistency.

Instead of calling FireConnectionClosed here, just don't dispose _socket here. Instead, close the uv_stream_handle only after both the output loop completed and

a) you've received a terminal read status or
b) the connection was aborted

In the case of b) you'd have to make sure to still call FireConnectionClosed when you close the socket ofc.

@@ -856,6 +852,7 @@ await using (var server = new TestServer(TestApp.EchoAppChunked, testContext))
await connection.Send(
"POST / HTTP/1.1");
connection.ShutdownSend();
await connection.TransportConnection.WaitForCloseTask;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this necessary?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed this offline. Calling ReceiveEnd unblocks the ProcessRequest loop allowing to observe the FIN and write a 4XX before the transport is aborted.

}

public override ValueTask<int> ReadAsync(Memory<byte> destination, CancellationToken cancellationToken = default)
{
return ReadAsyncInternal(destination);
return ReadAsyncInternal(destination, cancellationToken);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that we're flowing the cancellationToken through RawStream, do we have a regression test?

- Add CancelPendingRead to RawStream
- Clean up adapted pipeline complete
- Skipped flaky test
@davidfowl
Copy link
Member Author

@aspnet/build What's the deal with all the PRs, do we merge, do we wait? I know it's being looked at but what is the mitigation to unblock work?


public void CancelPendingRead()
{
_cancelCalled = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does CancelPendingRead need to be synchronized?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not for our usage.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't even think _cancelCalled needs to be volatile since CancelPendingRead acquires and releases the Pipe's _sync lock right afterwards.

@dougbu
Copy link
Contributor

dougbu commented Jun 13, 2019

@davidfowl as a few people have done, I suggest making a polite request for an admin to merge PRs where build success isn't being reported correctly or individual jobs hang. Looks like both of those issues have hit this PR but is it ready to merge?

@davidfowl
Copy link
Member Author

@davidfowl as a few people have done, I suggest making a polite request for an admin to merge PRs where build success isn't being reported correctly or individual jobs hang. Looks like both of those issues have hit this PR but is it ready to merge?

I can merge I just want to know the protocol. Yes this is ready to merge.

@dougbu
Copy link
Contributor

dougbu commented Jun 13, 2019

🆗, ping if you're blocked

@davidfowl davidfowl merged commit b0be780 into master Jun 13, 2019
@ghost ghost deleted the davidfowl/connection-unwind-refactor branch June 13, 2019 17:30
@amcasey amcasey added area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions and removed area-runtime labels Jun 6, 2023
@github-actions github-actions bot locked and limited conversation to collaborators Dec 8, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants