This is an automated email from the ASF dual-hosted git repository.

pan3793 pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/hadoop.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 8b0ffeffeb1 HADOOP-19881. Fix "port in use" detection in 
TestFrameDecoder (#8472)
8b0ffeffeb1 is described below

commit 8b0ffeffeb1906d7184b672405c16eed4054018d
Author: Cheng Pan <[email protected]>
AuthorDate: Fri May 8 15:42:01 2026 +0800

    HADOOP-19881. Fix "port in use" detection in TestFrameDecoder (#8472)
    
    Reviewed-by: Shilun Fan <[email protected]>
    Signed-off-by: Cheng Pan <[email protected]>
---
 .../org/apache/hadoop/oncrpc/TestFrameDecoder.java | 42 ++++++++++++++++++----
 1 file changed, 35 insertions(+), 7 deletions(-)

diff --git 
a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/oncrpc/TestFrameDecoder.java
 
b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/oncrpc/TestFrameDecoder.java
index a1d91751424..7a1d61cfcc0 100644
--- 
a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/oncrpc/TestFrameDecoder.java
+++ 
b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/oncrpc/TestFrameDecoder.java
@@ -22,6 +22,7 @@
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
+import java.net.BindException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Random;
@@ -235,19 +236,46 @@ private static int startRpcServer(boolean 
allowInsecurePorts)
             "localhost", serverPort, 100000, 1, 2, allowInsecurePorts);
         tcpServer = new SimpleTcpServer(serverPort, program, 1);
         tcpServer.run();
-        break;          // Successfully bound a port, break out.
-      } catch (InterruptedException | ChannelException e) {
+        return serverPort;    // Successfully bound a port.
+      } catch (InterruptedException e) {
         if (tcpServer != null) {
           tcpServer.shutdown();
         }
-        if (retries-- > 0) {
-          serverPort += rand.nextInt(20); // Port in use? Try another.
-        } else {
-          throw e;     // Out of retries.
+        Thread.currentThread().interrupt();
+        throw e;
+      } catch (Exception e) {
+        // Netty's ChannelFuture#sync may "sneaky-throw" a checked exception
+        // such as java.net.BindException via PlatformDependent#throwException,
+        // which is why catching ChannelException alone is not sufficient.
+        // Only retry on port-in-use style failures; rethrow anything else.
+        if (tcpServer != null) {
+          tcpServer.shutdown();
         }
+        if (!isPortInUse(e) || retries-- <= 0) {
+          throw e;     // Not a port-in-use error, or out of retries.
+        }
+        // Port in use? Try another. Ensure we never re-pick the same port.
+        serverPort += 1 + rand.nextInt(20);
+      }
+    }
+  }
+
+  /**
+   * Check whether the given exception indicates that the port is already
+   * bound by another process. Netty may wrap bind failures in a
+   * {@link ChannelException}, so inspect the cause chain and only treat
+   * {@link BindException}s that indicate an address-in-use condition as
+   * retryable.
+   */
+  private static boolean isPortInUse(Throwable t) {
+    Throwable cursor = t;
+    while (cursor != null) {
+      if (cursor instanceof BindException) {
+        return true;
       }
+      cursor = cursor.getCause();
     }
-    return serverPort;
+    return false;
   }
 
   static void createPortmapXDRheader(XDR xdr_out, int procedure) {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to