On Tue, 15 Aug 2023 17:30:54 GMT, Weibing Xiao <d...@openjdk.org> wrote:
> Please refer to JDK-8314063. > > The failure scenario is due to the setting of connection timeout. It is > either too small or not an optimal value for the system. When the client > tries to connect to the server with LDAPs protocol. It requires the handshake > after the socket is created and connected, but it fails due to connection > timeout and leaves the socket open. It is not closed properly due to the > exception handling in the JDK code. > > The change is adding a try/catch block and closing the socket in the catch > block, and the format of the code got changed consequently. Hello Weibing, The approach taken here seems resonable to me. Please find my comments on the fix and the test below: src/java.naming/share/classes/com/sun/jndi/ldap/Connection.java line 284: > 282: > 283: Socket socket = null; > 284: try { This method is hard to read. Readability could be improved by adding/splitting it into two new methods: - one for creating a socket with a use of specified socket factory - another one for creating a socket with `new Socket` src/java.naming/share/classes/com/sun/jndi/ldap/Connection.java line 369: > 367: } > 368: } > 369: } catch (Exception e) { The code wrapped in this try-catch block can throw unchecked exceptions, for example `SecurityException` thrown by `Socket.connect`. For such cases the newly created socket remain open. src/java.naming/share/classes/com/sun/jndi/ldap/Connection.java line 372: > 370: // 8314063 the socket is not closed after the failure of > handshake > 371: if (socket != null && !socket.isClosed()) { > 372: socket.close(); The original exception can be lost if `socket.close()` fails with `IOException` here test/jdk/com/sun/jndi/ldap/LdapSSLHandshakeFailureTest.java line 64: > 62: setKeyStore(); > 63: // start the test server first. > 64: TestServer server = new TestServer(); Since the `TestServer` implements `AutoClosable`, can we take advantage of that and of try-with-resources to close the server socket. One possibility is to move test server, url and environment table creation into try-catch block, and convert it to try-with-resources (`TestServer`). test/jdk/com/sun/jndi/ldap/LdapSSLHandshakeFailureTest.java line 66: > 64: TestServer server = new TestServer(); > 65: server.start(); > 66: url = "ldaps://localhost:" + server.getPortNumber(); The `URIBuilder` utility class from a test library can be used to construct a test server url here: URI uri = URIBuilder.newBuilder() .scheme("ldaps") .loopback() .port(server.getPortNumber()) .build(); test/jdk/com/sun/jndi/ldap/LdapSSLHandshakeFailureTest.java line 78: > 76: try { > 77: LdapContext ctx = new InitialLdapContext(env, null); > 78: ctx.close(); The context can be closed in finally block test/jdk/com/sun/jndi/ldap/LdapSSLHandshakeFailureTest.java line 151: > 149: private volatile boolean exceptionThrown; > 150: > 151: TestServer() throws IOException { `IOException` is not thrown by this constructor - can be removed test/jdk/com/sun/jndi/ldap/LdapSSLHandshakeFailureTest.java line 154: > 152: try { > 153: SSLServerSocketFactory socketFactory = > (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); > 154: serverSocket = socketFactory.createServerSocket(0); The test server can be bound to the loopback address here and `URIBuilder` test library class can be used to construct the `URL` as mentioned above: `socketFactory.createServerSocket(0, 0, InetAddress.getLoopbackAddress());` test/jdk/com/sun/jndi/ldap/LdapSSLHandshakeFailureTest.java line 166: > 164: } > 165: > 166: public boolean isExceptionThrown() { `isExceptionThrown` method is not used by the test test/jdk/com/sun/jndi/ldap/LdapSSLHandshakeFailureTest.java line 172: > 170: @Override > 171: public void run() { > 172: try (Socket socket = serverSocket.accept()) { Can be beautified a bit by putting socket, IS and OS into one try-with-resources statement. Something like: try (Socket socket = serverSocket.accept(); InputStream in = socket.getInputStream(); OutputStream out = socket.getOutputStream()) { ------------- PR Review: https://git.openjdk.org/jdk/pull/15294#pullrequestreview-1581104126 PR Review Comment: https://git.openjdk.org/jdk/pull/15294#discussion_r1296223224 PR Review Comment: https://git.openjdk.org/jdk/pull/15294#discussion_r1296269582 PR Review Comment: https://git.openjdk.org/jdk/pull/15294#discussion_r1296224057 PR Review Comment: https://git.openjdk.org/jdk/pull/15294#discussion_r1296226004 PR Review Comment: https://git.openjdk.org/jdk/pull/15294#discussion_r1296228008 PR Review Comment: https://git.openjdk.org/jdk/pull/15294#discussion_r1296229176 PR Review Comment: https://git.openjdk.org/jdk/pull/15294#discussion_r1296230459 PR Review Comment: https://git.openjdk.org/jdk/pull/15294#discussion_r1296232557 PR Review Comment: https://git.openjdk.org/jdk/pull/15294#discussion_r1296235296 PR Review Comment: https://git.openjdk.org/jdk/pull/15294#discussion_r1296236949