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