From d3d15e7113851780ca8a6ae72a62ad83f0c7a2d4 Mon Sep 17 00:00:00 2001 From: becomeStar Date: Sat, 7 Feb 2026 23:42:25 +0900 Subject: [PATCH 1/2] core: Fix inFlightSubStreams counting on retry commit Under certain retry and deadline timings, RetriableStream could leave the response future incomplete because inFlightSubStreams was not decremented consistently during commit. The change ensures inFlightSubStreams is decremented whenever a scheduled retry is committed, restoring correct close signaling without altering retry semantics. --- core/src/main/java/io/grpc/internal/RetriableStream.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/io/grpc/internal/RetriableStream.java b/core/src/main/java/io/grpc/internal/RetriableStream.java index 96816eb6f15..abc4b36d9fc 100644 --- a/core/src/main/java/io/grpc/internal/RetriableStream.java +++ b/core/src/main/java/io/grpc/internal/RetriableStream.java @@ -166,6 +166,7 @@ private Runnable commit(final Substream winningSubstream) { final boolean wasCancelled = (scheduledRetry != null) ? scheduledRetry.isCancelled() : false; final Future retryFuture; + final boolean retryWasScheduled = scheduledRetry != null; if (scheduledRetry != null) { retryFuture = scheduledRetry.markCancelled(); scheduledRetry = null; @@ -190,8 +191,10 @@ public void run() { substream.stream.cancel(CANCELLED_BECAUSE_COMMITTED); } } - if (retryFuture != null) { - retryFuture.cancel(false); + if (retryWasScheduled) { + if (retryFuture != null) { + retryFuture.cancel(false); + } if (!wasCancelled && inFlightSubStreams.decrementAndGet() == Integer.MIN_VALUE) { assert savedCloseMasterListenerReason != null; listenerSerializeExecutor.execute( From e9b84ae6b754aabd30042bf102200295cfc55f57 Mon Sep 17 00:00:00 2001 From: becomeStar Date: Sun, 8 Feb 2026 01:40:27 +0900 Subject: [PATCH 2/2] core: Use retryWasScheduled flag consistently --- core/src/main/java/io/grpc/internal/RetriableStream.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/io/grpc/internal/RetriableStream.java b/core/src/main/java/io/grpc/internal/RetriableStream.java index abc4b36d9fc..3b5f60ef545 100644 --- a/core/src/main/java/io/grpc/internal/RetriableStream.java +++ b/core/src/main/java/io/grpc/internal/RetriableStream.java @@ -167,7 +167,7 @@ private Runnable commit(final Substream winningSubstream) { final boolean wasCancelled = (scheduledRetry != null) ? scheduledRetry.isCancelled() : false; final Future retryFuture; final boolean retryWasScheduled = scheduledRetry != null; - if (scheduledRetry != null) { + if (retryWasScheduled) { retryFuture = scheduledRetry.markCancelled(); scheduledRetry = null; } else {