Skip to content

Handle Trailers-Only OK responses in streaming calls without exception handling#2697

Open
michaelmccord wants to merge 1 commit intogrpc:masterfrom
michaelmccord:master
Open

Handle Trailers-Only OK responses in streaming calls without exception handling#2697
michaelmccord wants to merge 1 commit intogrpc:masterfrom
michaelmccord:master

Conversation

@michaelmccord
Copy link

Summary

  • Avoid expensive TaskCanceledException in server streaming calls when the server returns a Trailers-Only response with OK status by setting HttpResponseTcs with TrySetResult before Cleanup runs
  • Add fallback in GetResponseStatus to read grpc-status from response headers when not found in trailers (Trailers-Only responses per gRPC spec)
  • Handle null HttpResponseMessage.Content on .NET Framework in HttpContentClientStreamReader.MoveNextCore
  • Remove await CallTask from GetResponseHeadersCoreAsync to prevent deadlock when ResponseHeadersAsync is awaited before MoveNext on streaming calls with status in headers

Fixes #2696

Test plan

  • AsyncServerStreamingCall_TrailersOnly_TrailersReturnedWithHeaders passes on all TFMs (net8.0, net9.0, net10.0, net462)
  • AsyncServerStreamingCall_NoMessagesSuccess_SuccussCommitLogged passes on all TFMs including net462
  • Full Grpc.Net.Client.Tests suite passes with 0 failures across all TFMs
  • No regressions in Grpc.AspNetCore.Server.Tests

@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Mar 12, 2026

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: michaelmccord / name: Michael McCord (b86a5d6)

Avoid expensive TaskCanceledException in streaming calls when the server
returns grpc-status in response headers (Trailers-Only). Set HttpResponseTcs
before cleanup so MoveNextCore can read the empty stream gracefully. Also
handle null HttpResponseMessage.Content on .NET Framework and read
grpc-status from response headers in GetResponseStatus as a fallback.
@JamesNK
Copy link
Member

JamesNK commented Mar 12, 2026

Why have lots of people immediately thumbs up this?

Do you know if there are existing unit tests for this scenario?

@michaelmccord
Copy link
Author

michaelmccord commented Mar 12, 2026

Why have lots of people immediately thumbs up this?

Do you know if there are existing unit tests for this scenario?

  1. I messaged a few people that knew I had been trying to track this problem down for a few days so that it would get attention.
  2. The tests I'm aware of are below (the ones which failed originally due to my inital changes and I subsequently fixed with additional code changes):
  • AsyncServerStreamingCallTests.AsyncServerStreamingCall_TrailersOnly_TrailersReturnedWithHeaders — test/Grpc.Net.Client.Tests/AsyncServerStreamingCallTests.cs
  • RetryTests.AsyncServerStreamingCall_NoMessagesSuccess_SuccussCommitLogged — test/Grpc.Net.Client.Tests/Retry/RetryTests.cs

One piece that I'm not entirely sure of is the removal of the await from GetResponseHeadersCoreAsync. It seemed to me that given my changes this was no longer necessary and it was causing a deadlock, but I wasn't 100% sure.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Server streaming Trailers-Only OK response uses expensive exception handling instead of graceful path

2 participants