8182757: JDWP: Socket Transport handshake hangs on Solaris
authorgthornbr
Thu, 03 Aug 2017 13:46:04 +0000
changeset 46091 a6f2dc91ba56
parent 46051 59e8c76ca7ba
child 46092 a24d70e09fb0
child 46879 5857274e1e42
8182757: JDWP: Socket Transport handshake hangs on Solaris Summary: Remove SO_REUSEADDR flag for non-fixed port sockets Reviewed-by: dcubed, sspitsyn, gtriantafill
jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/SocketTransportService.java
jdk/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c
--- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/SocketTransportService.java	Tue Aug 01 08:56:42 2017 -0700
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/SocketTransportService.java	Thu Aug 03 13:46:04 2017 +0000
@@ -275,6 +275,12 @@
             sa = new InetSocketAddress(localaddress, port);
         }
         ServerSocket ss = new ServerSocket();
+        if (port == 0) {
+            // Only need SO_REUSEADDR if we're using a fixed port. If we
+            // start seeing EADDRINUSE due to collisions in free ports
+            // then we should retry the bind() a few times.
+            ss.setReuseAddress(false);
+        }
         ss.bind(sa);
         return new SocketListenKey(ss);
     }
--- a/jdk/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c	Tue Aug 01 08:56:42 2017 -0700
+++ b/jdk/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c	Thu Aug 03 13:46:04 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -119,8 +119,26 @@
     return (char *)dbgsysTlsGet(tlsIndex);
 }
 
+/* Set options common to client and server sides */
 static jdwpTransportError
-setOptions(int fd)
+setOptionsCommon(int fd)
+{
+    jvalue dontcare;
+    int err;
+
+    dontcare.i = 0;  /* keep compiler happy */
+
+    err = dbgsysSetSocketOption(fd, TCP_NODELAY, JNI_TRUE, dontcare);
+    if (err < 0) {
+        RETURN_IO_ERROR("setsockopt TCPNODELAY failed");
+    }
+
+    return JDWPTRANSPORT_ERROR_NONE;
+}
+
+/* Set the SO_REUSEADDR option */
+static jdwpTransportError
+setReuseAddrOption(int fd)
 {
     jvalue dontcare;
     int err;
@@ -132,11 +150,6 @@
         RETURN_IO_ERROR("setsockopt SO_REUSEADDR failed");
     }
 
-    err = dbgsysSetSocketOption(fd, TCP_NODELAY, JNI_TRUE, dontcare);
-    if (err < 0) {
-        RETURN_IO_ERROR("setsockopt TCPNODELAY failed");
-    }
-
     return JDWPTRANSPORT_ERROR_NONE;
 }
 
@@ -350,10 +363,21 @@
         RETURN_IO_ERROR("socket creation failed");
     }
 
-    err = setOptions(serverSocketFD);
+    err = setOptionsCommon(serverSocketFD);
     if (err) {
         return err;
     }
+    if (sa.sin_port != 0) {
+        /*
+         * Only need SO_REUSEADDR if we're using a fixed port. If we
+         * start seeing EADDRINUSE due to collisions in free ports
+         * then we should retry the dbgsysBind() a few times.
+         */
+        err = setReuseAddrOption(serverSocketFD);
+        if (err) {
+            return err;
+        }
+    }
 
     err = dbgsysBind(serverSocketFD, (struct sockaddr *)&sa, sizeof(sa));
     if (err < 0) {
@@ -510,12 +534,18 @@
         RETURN_IO_ERROR("unable to create socket");
     }
 
-    err = setOptions(socketFD);
+    err = setOptionsCommon(socketFD);
     if (err) {
         return err;
     }
 
     /*
+     * We don't call setReuseAddrOption() for the non-server socket
+     * case. If we start seeing EADDRINUSE due to collisions in free
+     * ports then we should retry the dbgsysConnect() a few times.
+     */
+
+    /*
      * To do a timed connect we make the socket non-blocking
      * and poll with a timeout;
      */