runtime: HTTP2: Canceling token given to HttpClient.SendAsync does not send RST_STREAM

Found by a customer: https://twitter.com/stevejgordon/status/1169995743568048129

This is a high impact bug. A user will cancel a streaming gRPC call on the client, but the server will never be notified. If the server is checking CancellationToken.IsCancellationRequested then it will hang open forever.

This is a regression of https://github.com/dotnet/corefx/issues/38391

Related: https://github.com/dotnet/corefx/issues/39049


Repro:

  1. git clone https://github.com/JamesNK/grpc-dotnet.git
  2. git checkout jamesnk/duplex-cancellation-regression
  3. dotnet test test\FunctionalTests --filter Name~ServerStreaming_CancellationOnClient_SentToServer

Logic in the test is something like:

  1. Client makes a server streaming call to the server. This means the client is sending one message in the request’s HttpContent, which then completes.
  2. Server streams multiple messages to the client
  3. Client triggers the cancellation token given to gRPC client. HttpClient.SendAsync token is canceled
  4. The HttpClient should be sending RST_STREAM to the server, and the server should report the call is canceled. This isn’t happening so the server will stream messages forever.

Wireshark log: cancellation-regression.zip

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 20 (20 by maintainers)

Most upvoted comments

Confirmed disposing HttpResponseMessage works and no other gRPC unit tests regressed.

To echo what @stephentoub said: how is this different from existing tests we have, either for GRPC or HttpClient? We know that cancellation does send RST_STREAM for the tests we have, so what’s special about this?

The repo in the original issue should re-create it. However it won’t compile against the latest .NET Core SDK because of breaking changes.

I’m writing a new regression test now.