On Mon, 9 Feb 2026 16:40:37 GMT, Daniel Fuchs <[email protected]> wrote:
>> Can I please get a review of this change which proposes to fix the issue >> reported in https://bugs.openjdk.org/browse/JDK-8362268? >> >> The underlying issue here is simple - A `javax.naming.Context` for LDAP is >> backed by a JDK internal `com.sun.jndi.ldap.LdapCtx` instance. Each >> `LdapCtx` uses a `com.sun.jndi.ldap.LdapClient` instance to do the LDAP >> operations. Each `LdapClient` further uses a `com.sun.jndi.ldap.Connection` >> instance. Each `Connection` instance uses a `Socket` and the socket's >> `InputStream` and `OutputStream` to read/write LDAP messages from/to a LDAP >> server. Each `Connection` instance spawns a `Thread` to read (over the >> InputStream) and queue incoming messages from the LDAP server. >> >> When a LDAP backed `javax.naming.Context` initiates an operation, for >> example a `Context.lookup()`, then internally the LdapCtx initiates a LDAP >> request over the Connection's `OutputStream` and then waits for a LDAP >> response to arrive. In the issue reported here, it so happens that while >> reading over the `Connection`'s `InputStream`, the `InputStream.read()` >> raises an `IOException` (for whatever reason). That `IOException` rightly >> initiates the close of the `Connection` instance. Closing a `Connection` >> instance involves queuing a marker response for all waiting thread(s) to >> notice and raise an IOException, which they can ulimately propagate as a >> `NamingException` to the application. Additionally, the closing of the >> `Connection` also closes the `InputStream` and `OutputStream` of that >> `Connection`. >> >> When a thread that was waiting for a LDAP response, in LdapCtx, wakes up due >> to an IOException, it attempts to send a "abandon request" LDAP message over >> the `Connection`, so that the server knows that the client has abandoned the >> request. Since the Connection and its Input/OutputStream(s) are already >> closed, trying to write a message over the OutputStream can/will lead to an >> exception. The implementation of `Connection.abandonRequest(LdapRequest ldr, >> Control[] reqCtls)` which is where this code resides, guards against such >> exceptions by catching and ignoring an `IOException` from an >> `OutputStream.write(...)/flush()` call. >> >> Although `OutputStream.write(...)` is specified to throw an IOException if >> that stream is already closed, not all implementations adhere to that >> specification. For example, `java.io.BufferedOutputStream` does not throw >> any exception when `write(...)` is invoked on a closed `OutputStream`. >> Incidentally, the `Connection` instance's `Outp... > > src/java.naming/share/classes/com/sun/jndi/ldap/Connection.java line 554: > >> 552: // on a (closed) stream of a connection that can no >> longer be used. >> 553: return; >> 554: } > > I am not sure this is the right test. If I am not mistaken, this means that > "abandon request" will never be sent to the server, ever, since the flag is > set to false in cleanup() before abandonning requests. > Should we instead test whether the socket output is closed here? That's a good point. Like you note, I think we will have to check a different state here instead of `!useable`. I'll update the PR tomorrow after a more closer look. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/29638#discussion_r2783629638
