Potential infinite waiting at JMXConnection#createConnection
KUBOTA Yuji
kubota.yuji at gmail.com
Mon May 4 18:20:56 UTC 2015
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.
[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