Potential infinite waiting at JMXConnection#createConnection
KUBOTA Yuji
kubota.yuji at gmail.com
Mon May 4 18:55:25 UTC 2015
Hi all,
My apologies for the re-post and wrong link, the link [1] of the
initial post is not correctly.
The correct link is below.
[1]: http://hg.openjdk.java.net/jdk9/jdk9/jdk/file/c5b5d9045728/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPChannel.java#l227
The users cant specify the timeout by
sun.rmi.transport.tcp.responseTimeout, e.g. the second flush() of
TCPChannel#createConnection [2].
However, the first flush() [1] is not affected by
sun.rmi.transport.tcp.responseTimeout, and will be the (potential)
infinite waiting by bad luck.
[2]: http://hg.openjdk.java.net/jdk9/jdk9/jdk/file/c5b5d9045728/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPChannel.java#l296
Thanks,
Yuji
2015-05-05 1:19 GMT+09:00 KUBOTA Yuji <kubota.yuji at gmail.com>:
> Hi all,
>
> I want to contribute this issue.
> If there are a problem about this patch or a better way for openjdk
> community, please advise me.
>
> Thanks for
>
> 2015-04-22 0:31 GMT+09:00 KUBOTA Yuji <kubota.yuji at gmail.com>:
>> Hi all,
>>
>> I found an infinite waiting at TCPChannel#createConnection.
>> This method flushes the DataOutputStream without the socket timeout settings
>> when choose stream protocol [1].
>>
>> If connection lost (the destination server do no return response)
>> during the flush,
>> this method has possibilities to take long time beyond the expectations
>> at java.net.SocketInputStream.socketRead0 as following stack trace.
>>
>> stack trace :
>> at java.net.SocketInputStream.socketRead0(SocketInputStream.java)
>> at java.net.SocketInputStream.read(SocketInputStream.java)
>> at java.net.SocketInputStream.read(SocketInputStream.java)
>> at sun.security.ssl.InputRecord.readFully(InputRecord.java)
>> at sun.security.ssl.InputRecord.read(InputRecord.java)
>> at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java)
>> at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java)
>> at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java)
>> at sun.security.ssl.AppOutputStream.write(AppOutputStream.java)
>> at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java)
>> at java.io.BufferedOutputStream.flush(BufferedOutputStream.java)
>> at java.io.DataOutputStream.flush(DataOutputStream.java)
>> at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java)
>> at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java)
>> at sun.rmi.server.UnicastRef.invoke(UnicastRef.java)
>> at javax.management.remote.rmi.RMIServerImpl_Stub.newClient
>> at javax.management.remote.rmi.RMIConnector.getConnection(RMIConnector.java)
>> at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java)
>> at javax.management.remote.JMXConnectorFactory.connect(JMXConnectorFactory.java)
>>
>> When create connection, we cannot set the timeout by properties.
>> Therefore, JMX sets the default value of SO_TIMEOUT, i.e., infinite.
>> So I wrote a patch to fix this infinite waiting by using property-configured value:
>> sun.rmi.transport.tcp.responseTimeout.
>>
>> Please review this patch. :)
>>
>> Note: My OCA has been processed a few hour ago, so my name may take a
>> short time to
>> appear on the OCA signatories page.
>>
>> Thanks,
>> KUBOTA Yuji
>>
>> [1]: http://hg.openjdk.java.net/jdk9/jdk9/jdk/file/c5b5d9045728/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPConnection.java#l191
>>
>> 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
>> @@ -222,20 +222,34 @@
>> // choose protocol (single op if not reusable socket)
>> if (!conn.isReusable()) {
>> out.writeByte(TransportConstants.SingleOpProtocol);
>> } else {
>> out.writeByte(TransportConstants.StreamProtocol);
>> +
>> + int usableSoTimeout = 0;
>> + try {
>> + /*
>> + * If socket factory had set a zero timeout on its own,
>> + * then set the property-configured value to prevent
>> + * an infinite waiting.
>> + */
>> + 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();
>>
>> /*
>> * Set socket read timeout to configured value for JRMP
>> * 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
>> }
>>
>> @@ -279,18 +293,11 @@
>> * connection. NOTE: this timeout, if configured to a
>> * finite duration, places an upper bound on the time
>> * 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
>> }
>>
>> out.flush();
More information about the jdk9-dev
mailing list