From 57eb41bf62f283dda164144c40e178db7c278d4a Mon Sep 17 00:00:00 2001 From: Chi-Hsuan Huang Date: Sat, 2 May 2026 20:15:08 +0800 Subject: [PATCH] HDDS-14830. Handle interrupt gracefully in XceiverClientGrpc.sendCommandWithRetry --- .../hadoop/hdds/scm/XceiverClientGrpc.java | 3 +++ .../hdds/scm/TestXceiverClientGrpc.java | 27 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientGrpc.java b/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientGrpc.java index 1f9ac0a12267..8b1a99a6b668 100644 --- a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientGrpc.java +++ b/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientGrpc.java @@ -542,6 +542,9 @@ private XceiverClientReply sendCommandWithRetry( } catch (InterruptedException e) { LOG.error("Command execution was interrupted ", e); Thread.currentThread().interrupt(); + throw (IOException) new InterruptedIOException( + "Command " + processForDebug(request) + " was interrupted.") + .initCause(e); } } diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/hdds/scm/TestXceiverClientGrpc.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/hdds/scm/TestXceiverClientGrpc.java index 89ea363609d8..0f3af071fc54 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/hdds/scm/TestXceiverClientGrpc.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/hdds/scm/TestXceiverClientGrpc.java @@ -20,8 +20,10 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.IOException; +import java.io.InterruptedIOException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -148,6 +150,31 @@ public XceiverClientReply sendCommandAsync( assertEquals(0, allDNs.size()); } + @Test + public void testInterruptedCommandThrowsInterruptedIOException() + throws IOException { + final CompletableFuture response = + new CompletableFuture<>(); + try (XceiverClientGrpc client = new XceiverClientGrpc(pipeline, conf) { + @Override + public XceiverClientReply sendCommandAsync( + ContainerProtos.ContainerCommandRequestProto request, + DatanodeDetails dn) { + return new XceiverClientReply(response); + } + }) { + Thread.currentThread().interrupt(); + try { + InterruptedIOException ex = assertThrows(InterruptedIOException.class, + () -> invokeXceiverClientGetBlock(client)); + assertThat(ex).hasCauseInstanceOf(InterruptedException.class); + assertThat(Thread.currentThread().isInterrupted()).isTrue(); + } finally { + Thread.interrupted(); + } + } + } + @Test public void testFirstNodeIsCorrectWithTopologyForCommandTarget() throws IOException {