From d97b3b9e56bed52f6e7a1d4a65adffd174839b26 Mon Sep 17 00:00:00 2001 From: Timur Rakhmatullin <174210871+TimurRakhmatullin86@users.noreply.github.com> Date: Wed, 23 Sep 2026 18:25:36 -0700 Subject: [PATCH] Restore interrupt status in InterruptedException catch blocks Six files catch InterruptedException, wrap it in another exception, and re-throw without first calling Thread.currentThread().interrupt(). This silently clears the thread's interrupt flag, so callers checking Thread.isInterrupted() will miss that an interrupt occurred. The rest of the codebase (ClientCalls, NettyServer, OkHttpClientTransport, CsdsService, AsyncSecurityPolicy, etc.) already follows the correct pattern: restore the flag, then re-throw. These six are oversights. Files fixed: - TransmitStatusRuntimeExceptionInterceptor (4 catch blocks) - AltsHandshakerClient (3 catch blocks, split from multi-catch) - HandshakerServiceChannel (1 catch block in close()) - ChannelzProtoUtil (1 catch block) - XdsServerWrapper (1 catch block, split from multi-catch) - SslContextFactory (1 catch block, split from multi-catch) --- .../io/grpc/alts/HandshakerServiceChannel.java | 2 +- .../grpc/alts/internal/AltsHandshakerClient.java | 15 ++++++++++++--- .../internal/handshaker/SslContextFactory.java | 5 ++++- .../grpc/protobuf/services/ChannelzProtoUtil.java | 1 + ...TransmitStatusRuntimeExceptionInterceptor.java | 4 ++++ .../main/java/io/grpc/xds/XdsServerWrapper.java | 5 ++++- 6 files changed, 26 insertions(+), 6 deletions(-) diff --git a/alts/src/main/java/io/grpc/alts/HandshakerServiceChannel.java b/alts/src/main/java/io/grpc/alts/HandshakerServiceChannel.java index c914385a451..7db07fe3481 100644 --- a/alts/src/main/java/io/grpc/alts/HandshakerServiceChannel.java +++ b/alts/src/main/java/io/grpc/alts/HandshakerServiceChannel.java @@ -142,7 +142,7 @@ public void close() { try { terminated = delegate.awaitTermination(2, TimeUnit.SECONDS); } catch (InterruptedException ex) { - // terminated will be false + Thread.currentThread().interrupt(); } // Try hard to shutdown abruptly so any bug is more likely to be noticed during testing. long quietPeriodSeconds = terminated ? 0 : 1; diff --git a/alts/src/main/java/io/grpc/alts/internal/AltsHandshakerClient.java b/alts/src/main/java/io/grpc/alts/internal/AltsHandshakerClient.java index 9eb07f3e86d..8de02fa3cae 100644 --- a/alts/src/main/java/io/grpc/alts/internal/AltsHandshakerClient.java +++ b/alts/src/main/java/io/grpc/alts/internal/AltsHandshakerClient.java @@ -179,7 +179,10 @@ public ByteBuffer startClientHandshake() throws GeneralSecurityException { logger.log(ChannelLogLevel.DEBUG, "Send ALTS handshake request to upstream"); resp = handshakerStub.send(req.build()); logger.log(ChannelLogLevel.DEBUG, "Receive ALTS handshake response from upstream"); - } catch (IOException | InterruptedException e) { + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new GeneralSecurityException(e); + } catch (IOException e) { throw new GeneralSecurityException(e); } handleResponse(resp); @@ -201,7 +204,10 @@ public ByteBuffer startServerHandshake(ByteBuffer inBytes) throws GeneralSecurit HandshakerResp resp; try { resp = handshakerStub.send(req.build()); - } catch (IOException | InterruptedException e) { + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new GeneralSecurityException(e); + } catch (IOException e) { throw new GeneralSecurityException(e); } handleResponse(resp); @@ -231,7 +237,10 @@ public ByteBuffer next(ByteBuffer inBytes) throws GeneralSecurityException { logger.log(ChannelLogLevel.DEBUG, "Send ALTS handshake request to upstream"); resp = handshakerStub.send(req.build()); logger.log(ChannelLogLevel.DEBUG, "Receive ALTS handshake response from upstream"); - } catch (IOException | InterruptedException e) { + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new GeneralSecurityException(e); + } catch (IOException e) { throw new GeneralSecurityException(e); } handleResponse(resp); diff --git a/s2a/src/main/java/io/grpc/s2a/internal/handshaker/SslContextFactory.java b/s2a/src/main/java/io/grpc/s2a/internal/handshaker/SslContextFactory.java index e586b51a76f..4bc98497c55 100644 --- a/s2a/src/main/java/io/grpc/s2a/internal/handshaker/SslContextFactory.java +++ b/s2a/src/main/java/io/grpc/s2a/internal/handshaker/SslContextFactory.java @@ -75,7 +75,10 @@ static SslContext createForClient( GetTlsConfigurationResp.ClientTlsConfiguration clientTlsConfiguration; try { clientTlsConfiguration = getClientTlsConfigurationFromS2A(stub, localIdentity); - } catch (IOException | InterruptedException e) { + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new GeneralSecurityException("Failed to get client TLS configuration from S2A.", e); + } catch (IOException e) { throw new GeneralSecurityException("Failed to get client TLS configuration from S2A.", e); } diff --git a/services/src/main/java/io/grpc/protobuf/services/ChannelzProtoUtil.java b/services/src/main/java/io/grpc/protobuf/services/ChannelzProtoUtil.java index 74448a8c5bf..858e8823276 100644 --- a/services/src/main/java/io/grpc/protobuf/services/ChannelzProtoUtil.java +++ b/services/src/main/java/io/grpc/protobuf/services/ChannelzProtoUtil.java @@ -489,6 +489,7 @@ private static T getFuture(ListenableFuture future) { } return ret; } catch (InterruptedException e) { + Thread.currentThread().interrupt(); throw Status.INTERNAL.withCause(e).asRuntimeException(); } catch (ExecutionException e) { throw Status.INTERNAL.withCause(e).asRuntimeException(); diff --git a/util/src/main/java/io/grpc/util/TransmitStatusRuntimeExceptionInterceptor.java b/util/src/main/java/io/grpc/util/TransmitStatusRuntimeExceptionInterceptor.java index e4b364bd532..6f2864fde69 100644 --- a/util/src/main/java/io/grpc/util/TransmitStatusRuntimeExceptionInterceptor.java +++ b/util/src/main/java/io/grpc/util/TransmitStatusRuntimeExceptionInterceptor.java @@ -194,6 +194,7 @@ public void run() { try { return retVal.get(); } catch (InterruptedException e) { + Thread.currentThread().interrupt(); throw new RuntimeException(ERROR_MSG, e); } catch (ExecutionException e) { throw new RuntimeException(ERROR_MSG, e); @@ -212,6 +213,7 @@ public void run() { try { return retVal.get(); } catch (InterruptedException e) { + Thread.currentThread().interrupt(); throw new RuntimeException(ERROR_MSG, e); } catch (ExecutionException e) { throw new RuntimeException(ERROR_MSG, e); @@ -261,6 +263,7 @@ public void run() { try { return retVal.get(); } catch (InterruptedException e) { + Thread.currentThread().interrupt(); throw new RuntimeException(ERROR_MSG, e); } catch (ExecutionException e) { throw new RuntimeException(ERROR_MSG, e); @@ -280,6 +283,7 @@ public void run() { try { return retVal.get(); } catch (InterruptedException e) { + Thread.currentThread().interrupt(); throw new RuntimeException(ERROR_MSG, e); } catch (ExecutionException e) { throw new RuntimeException(ERROR_MSG, e); diff --git a/xds/src/main/java/io/grpc/xds/XdsServerWrapper.java b/xds/src/main/java/io/grpc/xds/XdsServerWrapper.java index eb6d5bda0fd..0009e15e9ac 100644 --- a/xds/src/main/java/io/grpc/xds/XdsServerWrapper.java +++ b/xds/src/main/java/io/grpc/xds/XdsServerWrapper.java @@ -340,7 +340,10 @@ public void run() { Exception exception; try { exception = initialStartFuture.get(); - } catch (InterruptedException | ExecutionException e) { + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException(e); + } catch (ExecutionException e) { throw new RuntimeException(e); } if (exception != null) {