-
Notifications
You must be signed in to change notification settings - Fork 5.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
8313657 : com.sun.jndi.ldap.Connection.cleanup does not close connections on SocketTimeoutErrors #15143
Conversation
…ions on SocketTimeoutErrors
👋 Welcome back weibxiao! A progress list of the required criteria for merging this PR into |
sock.close(); | ||
unpauseReader(); | ||
if (debug) { | ||
if (sock.isClosed()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is it possible for sock.close() to succeed but isClosed to return false?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is an unreachable code and got removed.
Webrevs
|
why not restructure the finally block a little ... refactor extract methods
...
|
import javax.naming.directory.DirContext; | ||
import javax.naming.directory.InitialDirContext; | ||
import javax.net.SocketFactory; | ||
import java.io.*; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we please use a set of class imports instead of package import here:
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
* @library /test/lib | ||
*/ | ||
|
||
public class SocketCloseTest { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we change the test location from test/javax/naming/InitialContext
to an LDAP-implementation specific folder - test/jdk/com/sun/jndi/ldap
48, 12, 2, 1, 1, 97, 7, 10, 1, 0, 4, 0, 4, 0 | ||
}; | ||
private static final int SEARCH_SIZE = 87; | ||
private static final byte[] SEARCH_RESPONSE = new byte[]{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SEARCH_RESPONSE
, SEARCH_SIZE
and BIND_SIZE
are not used in the test. If they're not needed they can be removed.
Hashtable<String, Object> props = new Hashtable<>(); | ||
|
||
props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); | ||
props.put(Context.PROVIDER_URL, "ldap://localhost:1389/o=example"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For future test maintainers - can we please clarify that the hostname and port do not matter here because the provided custom socket factory doesn't establish a connection to the specified provider URL
@@ -650,6 +650,19 @@ void cleanup(Control[] reqCtls, boolean notifyParent) { | |||
} catch (IOException ie) { | |||
if (debug) | |||
System.err.println("Connection: problem closing socket: " + ie); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about combining the debug statement here with the one below and just print the socket isClosed state, something like
if (debug) {
System.err.println("Connection: problem cleaning-up the connection: " + ie);
System.err.println("Socket isClosed: " + sock.isClosed());
}
The text was changed here since the exception can also be thrown by unpauseReader
} | ||
} catch (IOException ioe) { | ||
if (debug) | ||
System.err.println("Connection::cleanup problem: " + ioe); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe change the message here to highlight the fact that it's the 2nd attemp to clean-up the connection
|
@@ -684,6 +682,43 @@ void cleanup(Control[] reqCtls, boolean notifyParent) { | |||
} | |||
} | |||
|
|||
// flush and close output stream | |||
private void flushCloseOutputStream() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'flushAndCloseOutputStream' will be more meaningful name.
} | ||
|
||
// close socket | ||
private void closeConnectionSocket() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'closeSocketConnection' will be more meaningful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the suggested name was to convey the closing of the Connection's socket, not a socket connection per se.
I ran the test multiple times in mach5 and it executes fine. However, while examining the log output I noticed the "The socket was not closed. " output. This is a little confusing. While looking at the test and exploring the origins of this outout, we see that the test is essentially an othervm execution. As such, I restructured the test to othervm and it executes with some informative output and eliminates the discombobulating output. I have left a comment in the JBS bug item with some further details and changes for othervm. This gives some imformative output as the test executes. The origins of the output is the main try block executing in the agentvm and the throwing of a ClassNotFoundException. If you don't wish to do otherrvm and to avoid the "The socket was not closed. " output, and if wish to retain the same structure, then consider adding a run command to the test with an arg, and then a conditional on the core test logic e.g.
and in the main method
if (args.length == 0) { // only executed in the launched JVM
|
props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); | ||
props.put(Context.PROVIDER_URL, "ldap://localhost:1389/o=example"); | ||
props.put("java.naming.ldap.factory.socket", CustomSocketFactory.class.getName()); | ||
try { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this will execute twice: once in the agentvm main and also, as desired, in the test JVM main.
The agentvm main sees a ClassNotFoundException being thrown and then the output of "The socket was not closed. " in the log c.f. other comments and bug comments for further details to avoid execution in agentvm or use of othervm test mode execution
|
public static class LdapInputStream extends InputStream { | ||
private LdapOutputStream los; | ||
private ByteArrayInputStream bos; | ||
int pos = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
variable 'pos' is not used can be removed.
@Override | ||
public int read() throws IOException { | ||
bos = new ByteArrayInputStream(BIND_RESPONSE); | ||
int next = bos.read(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can be simplified as follows return bos.read();
} | ||
|
||
public static class CustomSocketFactory extends SocketFactory { | ||
public static CustomSocket customSocket = new CustomSocket(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can make 'customSocket' to private.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Latest code looks OK to me.
} | ||
|
||
private static class LdapInputStream extends InputStream { | ||
private LdapOutputStream los; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The LdapOutputStream
reference is not used by LdapInputStream
, therefore the los
field can be removed:
private static class LdapInputStream extends InputStream {
- private LdapOutputStream los;
private ByteArrayInputStream bos;
- public LdapInputStream(LdapOutputStream los) {
- this.los = los;
+ public LdapInputStream() {
}
@Override
@@ -144,7 +142,7 @@ public class SocketCloseTest {
private static class CustomSocket extends Socket {
private int closeMethodCalled = 0;
private LdapOutputStream output = new LdapOutputStream();
- private LdapInputStream input = new LdapInputStream(output);
+ private LdapInputStream input = new LdapInputStream();
public void connect(SocketAddress address, int timeout) {
}
Updated LdapInputStream.java and remove the unused variable. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for incorporating the feedback
LGTM
@weibxiao This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be:
You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 107 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. As you do not have Committer status in this project an existing Committer must agree to sponsor your change. Possible candidates are the reviewers of this PR (@vyommani, @msheppar, @AlekseiEfimov) but any other Committer may sponsor as well. ➡️ To flag this PR as ready for integration with the above commit message, type |
/integrate |
/sponsor |
Going to push as commit e56d3bc.
Your commit was automatically rebased without conflicts. |
@AlekseiEfimov @weibxiao Pushed as commit e56d3bc. 💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored. |
com.sun.jndi.ldap.Connection::leanup does not close the underlying socket if the is an IOException generation when the output stream was flushing the buffer.
Please refer to the bug https://bugs.openjdk.org/browse/JDK-8313657.
Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/15143/head:pull/15143
$ git checkout pull/15143
Update a local copy of the PR:
$ git checkout pull/15143
$ git pull https://git.openjdk.org/jdk.git pull/15143/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 15143
View PR using the GUI difftool:
$ git pr show -t 15143
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/15143.diff
Webrev
Link to Webrev Comment