Potential infinite waiting at JMXConnection#createConnection

KUBOTA Yuji kubota.yuji at gmail.com
Wed May 6 11:07:44 UTC 2015


2015-05-06 19:48 GMT+09:00 Shanliang Jiang <shanliang.jiang at oracle.com>:

> To reproduce the bug, I was thinking to use RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE to specify a user socket server, which will not response any client connection request, I did not yet test this solution.

Thanks, I will try to reproduce with the attribute at first.

Yuji

> Shanliang
>
>
> Thanks,
> Yuji
>
> 2015-05-06 18:51 GMT+09:00 Shanliang Jiang <shanliang.jiang at oracle.com>:
>>
>> Hi Yuji,
>>
>> I think better at first to create a bug at:
>>     https://bugs.openjdk.java.net/secure/Dashboard.jspa
>>
>> It looks like an issue for me, it must be possible to have a test to reproduce the issue. It is helpful to attach the test and present your solution in the bug.
>>
>> I can help if you need any help to create the bug.
>>
>> Shanliang
>>
>>
>>
>> KUBOTA Yuji wrote:
>>
>> My apologies for re-post, I forgot to register serviceability-dev before the last post.
>>
>> Hi Shanliang,
>>
>> Thanks you for your help!
>>
>> RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE is a nice workaround.
>>
>> However, many users believe sun.rmi.transport.tcp.responseTimeout to specify the timeout,
>> e.g. the second flush() of TCPChannel#createConnection [2].
>> In really, the first flush() [3] is not affected by sun.rmi.transport.tcp.responseTimeout,
>> and will be the (potential) infinite waiting by bad luck. So I think openjdk should fix it for users.
>>
>> [2]: http://hg.openjdk.java.net/jdk9/jdk9/jdk/file/c5b5d9045728/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPChannel.java#l296
>> [3]: http://hg.openjdk.java.net/jdk9/jdk9/jdk/file/c5b5d9045728/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPChannel.java#l227
>>
>> Thanks,
>> Yuji
>>
>> 2015-05-05 2:03 GMT+09:00 Shanliang Jiang <shanliang.jiang at oracle.com>:
>> > Hi Yuji,
>> >
>> > (I reply to serviceability alias)
>> >
>> > When you create a RMI server connector, you can specify a
>> > RMIClientSocketFactory by RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE, this allows
>> > you to specify your SoTimeout.
>> >
>> > Hope this helps.
>> >
>> > Shanliang
>> >
>> >
>> >
>> > KUBOTA Yuji 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 serviceability-dev mailing list