[PING] Potential infinite waiting at JMXConnection#createConnection
KUBOTA Yuji
kubota.yuji at gmail.com
Mon Jan 4 14:14:31 UTC 2016
Hi all,
Could you please review this patch?
Thanks,
Yuji
2015-12-17 2:05 GMT+09:00 KUBOTA Yuji <kubota.yuji at gmail.com>:
> Hi all,
>
> If Shanliang cannot review, someone could review it?
>
> I reported this issue first at the below.
> http://mail.openjdk.java.net/pipermail/jdk9-dev/2015-April/002152.html
> http://mail.openjdk.java.net/pipermail/serviceability-dev/2015-May/017241.html
>
> Hope this patch helps to community.
>
> Thanks,
> Yuji
>
> 2015-12-10 22:40 GMT+09:00 KUBOTA Yuji <kubota.yuji at gmail.com>:
>> Hi Shanliang and all,
>>
>> Sorry my reply is too late. But, finally, I reproduced this issue by
>> following test program! :)
>> Could you please review test program and my patch ?
>>
>> The test program includes some files, but I do not have an account of
>> openjdk, so I push it on icedtea server as below.
>>
>> http://icedtea.classpath.org/people/ykubota/fixLoopAtJMXConnectorFactory/file/e31044f0804f
>>
>> The test program starts a simple sleep server program (JMXSSLServer)
>> on external jdb process with a breakpoint at
>> sun.security.ssl.ServerHandshaker.clientHello set. It then starts a
>> client process (JMXSSLCient) which tries to connect the sleep/jdb
>> process.
>> ServerHandshaker.clientHello responds to the client hello message and
>> sends SSL record back. By setting breakpont in that function, we can
>> emulate this issue in which client keeps waiting SSL record from
>> server.
>> Now, JMXConnectorFactory.connect() ignores
>> sun.rmi.transport.tcp.responseTimeout, so wait the response (SSL
>> record) from server INFINITELY. Once my patch (jdk9.patch) was added,
>> then the client will return 0 when the connection timeout happen by
>> sun.rmi.transport.tcp.responseTimeout.
>> And test program returns the client's return code.
>>
>> You can reproduce infinite waiting by the below.
>> * hg clone http://icedtea.classpath.org/people/ykubota/fixLoopAtJMXConnectorFactory/
>> * cd fixLoopAtJMXConnectorFactory/testProgram
>> * set JAVA_HOME
>> * mvn package
>> * setting debugcontrol.properties if you need.
>> * *NOTE* This test program will stop for "debugcontroltest.stop_time" ms.
>> * ${JAVA_HOME}/bin/java -cp .:target/debugcontrol-1.0-SNAPSHOT.jar
>> debugcontrol.DebugController
>>
>> * The result by JDK without my patch.
>> The client throws java.net.ConnectException after sending quit to jdb.
>> ------
>> [INFO] Server process args
>> args[0] /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.65-3.b17.fc23.x86_64/bin/jdb
>> :
>> :
>> cli-out: [INFO] Service URL: service:jmx:rmi:///jndi/rmi://localhost:9876/jmxrmi
>> ser-err: Set deferred breakpoint sun.security.ssl.ServerHandshaker.clientHello
>> ser-out:
>> ser-err: Breakpoint hit: "thread=RMI TCP Connection(2)-127.0.0.1",
>> sun.security.ssl.ServerHandshaker.clientHello(), line=339 bci=0
>> ser-out:
>> [INFO] sending quit to jdb
>> ser-err: RMI TCP Connection(2)-127.0.0.1[1]
>> cli-err: java.rmi.ConnectException: Connection refused to host:
>> 127.0.0.1; nested exception is:
>> cli-err: java.net.ConnectException: Connection refused
>> cli-err: at
>> sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:619)
>> cli-err: at
>> sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:216)
>> cli-err: at
>> sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202)
>> cli-err: at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:130)
>> cli-err: at
>> javax.management.remote.rmi.RMIServerImpl_Stub.newClient(Unknown
>> Source)
>> cli-err: at
>> javax.management.remote.rmi.RMIConnector.getConnection(RMIConnector.java:2432)
>> cli-err: at
>> javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:308)
>> cli-err: at
>> javax.management.remote.JMXConnectorFactory.connect(JMXConnectorFactory.java:270)
>> cli-err: at
>> debugcontrol.client.JMXSSLClient.execute(JMXSSLClient.java:51)
>> cli-err: at debugcontrol.client.JMXSSLClient.main(JMXSSLClient.java:34)
>> cli-err: Caused by: java.net.ConnectException: Connection refused
>> cli-err: at java.net.PlainSocketImpl.socketConnect(Native Method)
>> cli-err: at
>> java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
>> cli-err: at
>> java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
>> cli-err: at
>> java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
>> cli-err: at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
>> cli-err: at java.net.Socket.connect(Socket.java:589)
>> cli-err: at
>> sun.security.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:668)
>> cli-err: at sun.security.ssl.SSLSocketImpl.<init>(SSLSocketImpl.java:427)
>> cli-err: at
>> sun.security.ssl.SSLSocketFactoryImpl.createSocket(SSLSocketFactoryImpl.java:88)
>> cli-err: at
>> javax.rmi.ssl.SslRMIClientSocketFactory.createSocket(SslRMIClientSocketFactory.java:121)
>> cli-err: at
>> sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613)
>> cli-err: ... 9 more
>> [INFO] Thu Dec 10 16:16:50 JST 2015 Client done. Result code: 2
>> [INFO] Client took 114462 msec.
>>
>> * By JDK 9 with my patch.
>> The client got java.net.SocketTimeoutException after the connection
>> timeout happen, then return 0.
>> ------
>> [INFO] Server process args
>> args[0] /workspace/jdk9-netdev-patch/build/linux-x86_64-normal-server-release/jdk/bin/jdb
>> args[1] -classpath
>> args[2] target/classes
>> args[3] -J-Duser.language=en
>> args[4] -Dcom.sun.management.jmxremote.port=9876
>> args[5] -Dcom.sun.management.jmxremote.password.file=jmxremote.password
>> args[6] -Djavax.net.ssl.keyStore=jmx-test-cert.pkcs12
>> args[7] -Djavax.net.ssl.keyStoreType=pkcs12
>> args[8] -Djavax.net.ssl.keyStorePassword=changeit
>> args[9] debugcontrol.server.JMXSSLServer
>> ser-out: Initializing jdb ...
>> ser-err: > Deferring breakpoint sun.security.ssl.ServerHandshaker.clientHello.
>> ser-out: It will be set after the class is loaded.
>> ser-err: > run debugcontrol.server.JMXSSLServer
>> ser-err: Set uncaught java.lang.Throwable
>> ser-out: Set deferred uncaught java.lang.Throwable
>> ser-err: >
>> ser-out: VM Started: [INFO] Server launched then sleep...
>> [INFO] Client process args:
>> args[0] /workspace/jdk9-netdev-patch/build/linux-x86_64-normal-server-release/jdk/bin/java
>> args[1] -classpath
>> args[2] target/classes
>> args[3] -Duser.language=en
>> args[4] -Djavax.net.ssl.trustStore=jmx-test-cert.pkcs12
>> args[5] -Djavax.net.ssl.trustStoreType=pkcs12
>> args[6] -Djavax.net.ssl.trustStorePassword=changeit
>> args[7] -Dsun.rmi.transport.tcp.responseTimeout=1000
>> args[8] -Dsun.rmi.transport.tcp.handshakeTimeout=1000
>> args[9] debugcontrol.client.JMXSSLClient
>> args[10] localhost
>> args[11] 9876
>> cli-out: [INFO] Service URL: service:jmx:rmi:///jndi/rmi://localhost:9876/jmxrmi
>> ser-err: Set deferred breakpoint sun.security.ssl.ServerHandshaker.clientHello
>> ser-out:
>> ser-err: Breakpoint hit: "thread=RMI TCP Connection(2)-127.0.0.1",
>> sun.security.ssl.ServerHandshaker.clientHello(), line=356 bci=0
>> ser-out:
>> cli-out: [INFO] Conglaturation. We got a timeout.
>> [INFO] Thu Dec 10 15:54:39 JST 2015 Client done. Result code: 0
>>
>>
>> * My patch (no change from the reported)
>> * http://icedtea.classpath.org/people/ykubota/fixLoopAtJMXConnectorFactory/file/e31044f0804f/jdk9.patch
>> ------
>> diff --git a/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPChannel.java
>> b/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPChannel.java
>> --- a/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPChannel.java
>> +++ b/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPChannel.java
>> @@ -224,6 +224,22 @@
>> out.writeByte(TransportConstants.SingleOpProtocol);
>> } else {
>> out.writeByte(TransportConstants.StreamProtocol);
>> +
>> + int usableSoTimeout = 0;
>> + try {
>> + /*
>> + * If socket factory had set a non-zero timeout on its
>> + * own, then restore it instead of using the property-
>> + * configured value.
>> + */
>> + usableSoTimeout = sock.getSoTimeout();
>> + if (usableSoTimeout == 0) {
>> + usableSoTimeout = responseTimeout;
>> + }
>> + sock.setSoTimeout(usableSoTimeout);
>> + } catch (Exception e) {
>> + // if we fail to set this, ignore and proceed anyway
>> + }
>> out.flush();
>>
>> /*
>> @@ -231,9 +247,7 @@
>> * connection handshake; this also serves to guard against
>> * non-JRMP servers that do not respond (see 4322806).
>> */
>> - int originalSoTimeout = 0;
>> try {
>> - originalSoTimeout = sock.getSoTimeout();
>> sock.setSoTimeout(handshakeTimeout);
>> } catch (Exception e) {
>> // if we fail to set this, ignore and proceed anyway
>> @@ -281,14 +295,7 @@
>> * that a remote method call is permitted to execute.
>> */
>> try {
>> - /*
>> - * If socket factory had set a non-zero timeout on its
>> - * own, then restore it instead of using the property-
>> - * configured value.
>> - */
>> - sock.setSoTimeout((originalSoTimeout != 0 ?
>> - originalSoTimeout :
>> - responseTimeout));
>> + sock.setSoTimeout(usableSoTimeout);
>> } catch (Exception e) {
>> // if we fail to set this, ignore and proceed anyway
>> }
>>
>> Thanks,
>> Yuji
More information about the serviceability-dev
mailing list