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.y...@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.y...@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();