Skip to content

Handle exceptions during draining pending calls / streams#12737

Open
kannanjgithub wants to merge 5 commits intogrpc:masterfrom
kannanjgithub:framer-exception-stream-hang
Open

Handle exceptions during draining pending calls / streams#12737
kannanjgithub wants to merge 5 commits intogrpc:masterfrom
kannanjgithub:framer-exception-stream-hang

Conversation

@kannanjgithub
Copy link
Copy Markdown
Contributor

@kannanjgithub kannanjgithub commented Mar 30, 2026

The reported hang in issue #12109 in blockingUnaryCall was caused by an unhandled framing exception during the draining of DelayedStream. When MessageFramer throws an
exception (e.g., RESOURCE_EXHAUSTED), it bubbles up through DelayedStream.drainPendingCalls and is eventually caught and swallowed by ThreadlessExecutor.runQuietly. This leaves the DelayedStream in an inconsistent state (where passThrough is still false), and the responseFuture never completes, causing the blocking call to hang forever.

This fix adds proper exception handling to the draining loops in both DelayedStream and DelayedClientCall. When an exception occurs during draining:

  1. The realStream (or realCall) is explicitly cancelled with the error.
  2. The pending calls are cleared.
  3. The stream/call transitions to passThrough = true to prevent getting stuck.
  4. The listener's pending callbacks are drained, ensuring that any closure notifications are delivered to the application.

…handled framing exception during the draining of DelayedStream. When MessageFramer throws an

  exception (e.g., RESOURCE_EXHAUSTED), it bubbles up through DelayedStream.drainPendingCalls and is eventually caught and swallowed by
  ThreadlessExecutor.runQuietly. This leaves the DelayedStream in an inconsistent state (where passThrough is still false), and the responseFuture never
  completes, causing the blocking call to hang forever.

  I have implemented a fix that adds proper exception handling to the draining loops in both DelayedStream and DelayedClientCall. When an exception occurs
  during draining:
   1. The realStream (or realCall) is explicitly cancelled with the error.
   2. The pending calls are cleared.
   3. The stream/call transitions to passThrough = true to prevent getting stuck.
   4. The listener's pending callbacks are drained, ensuring that any closure notifications are delivered to the application.
@kannanjgithub kannanjgithub changed the title Handle exceptions during draining pending calls Handle exceptions during draining pending calls / streams Mar 30, 2026
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.

1 participant