Potential infinite waiting at JMXConnection#createConnection

Shanliang Jiang shanliang.jiang at oracle.com
Wed May 6 10:48:49 UTC 2015


KUBOTA Yuji wrote:
> Hi Shanliang,
>
> Many thanks for your help! 
>
> I do not have any role yet. So I can not create a new bug at JBS. It's 
> a reason why I submitted a mail with my patch at first.
>
> This issue is caused by a rare network problem during the flush() [3] 
> . I got this infinite loop only once. So I will try to write test 
> or/and client codes with BCI for reproduction.
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.

Shanliang
>
> Thanks,
> Yuji
>
> 2015-05-06 18:51 GMT+09:00 Shanliang Jiang <shanliang.jiang at oracle.com 
> <mailto: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 <mailto: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
>>     <mailto: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();
>>     >    
>>     >
>>     >
>>
>
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/serviceability-dev/attachments/20150506/06234dad/attachment.html>


More information about the serviceability-dev mailing list