Potential infinite waiting at JMXConnection#createConnection

Ben Evans benjamin.john.evans at gmail.com
Mon May 4 17:22:51 UTC 2015


Try again with the correct Adopt address...

On Mon, May 4, 2015 at 6:22 PM, Ben Evans <benjamin.john.evans at gmail.com> wrote:
> Hi Kubota,
>
> I think that perhaps the AdoptOpenJDK project
> (https://java.net/projects/adoptopenjdk) can help here.
>
> I've copied in their mailing list, in case one of the developers there
> can help you.
>
> Thanks,
>
> Ben
>
> On Mon, May 4, 2015 at 5:19 PM, KUBOTA Yuji <kubota.yuji at gmail.com> wrote:
>> 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 adoption-discuss mailing list