To follow along one needs to understand how some Tomcat attributes have been renamed in subsequent releases: New Name Old Name -------- -------- acceptCount -> backlog connectionLinger -> soLinger connectionTimeout -> soTimeout connectionUploadTimeout -> timeout clientAuth -> clientauth keystoreFile -> keystore randomFile -> randomfile rootFile -> rootfile keystorePass -> keypass keystoreType -> keytype sslProtocol -> protocol sslProtocols -> protocols We want to examine the connectionTimeout attribute and how it applies to sockets, this is defined here: Apache Tomcat Configuration Reference: The HTTP Connector http://tomcat.apache.org/tomcat-6.0-doc/config/http.html connectionTimeout: The number of milliseconds this Connector will wait, after accepting a connection, for the request URI line to be presented. Note, the critical piece of information here, the timeout applies AFTER the accept completes, there is no timeout on the accept operation. In JSS's SSLServerSocket.accept() method it does this: socketPointer = socketAccept(s, base.getTimeout(), handshakeAsClient); By looking at the following definitions and the attribute renaming: class SocketBase { private int timeout; int getTimeout() { return timeout; } void setTimeout(int timeout) { this.timeout = timeout; } } public class SSLServerSocket extends java.net.ServerSocket { public void setSoTimeout(int timeout) { base.setTimeout(timeout); } public int getSoTimeout() { return base.getTimeout(); } } you can see that socketPointer = socketAccept(s, base.getTimeout(), handshakeAsClient); is equivalent to: socketPointer = socketAccept(s, connectionTimeout, handshakeAsClient); But the connectionTimeout is NOT supposed to be applied to the accept operation, it is to be applied AFTER the socket accept completes to the NEW socket returned by the the accept. JIoEndPoint.java (and other connectors) do this or sometime very similar: serverSocketFactory.acceptSocket(serverSocket); which eventually gets around to calling serverSocket.setSocketOptions() which then does this: if (soTimeout > 0) { socket.setSoTimeout(soTimeout); } Which if you follow the attribute renaming is the same things as if (connectionTimeout > 0) { socket.setSoTimeout(connectionTimeout); } Which implements the defined behavior for connectionTimeout. Thus: socketPointer = socketAccept(s, base.getTimeout(), handshakeAsClient); is incorrect, the timeout should not be applied to the accept operation, the layers above will drive the low level JSS Socket settings and set the timeout's and other socket attributes when appropriate and the values appropriate for the socket in question (there are different timeouts). JSS is a low level implemenation, it should not set parameters it was not told to set. Therefore the socketAccept should replace the 2nd parameter with zero like this because zero implies PR_INTERVAL_NO_TIMEOUT, this is the correct code: socketPointer = socketAccept(s, 0, handshakeAsClient);
Created attachment 462081 [details] Original comment without whitespace mangling for easier reading
Created attachment 462082 [details] patch fixing timeout parameter to acceptSocket
We had thought this issue could be postponed by not setting the connectionTimeout in the server.xml file, however that is not the case. Even when we don't set the connectionTimeout a socket accept timeout is being thrown. Apparently this is due to JSSSocketFactory.initializeSocket() which calls setSoTimeout(120*1000). This is wrong. None of the layers above JSS have asked JSS to set the connection timeout. JSS is a low level set of socket utilities, it is not supposed to be making "policy", policy comes from the layers above it. Even after having removed connectionTimeout setting in server.xml the timeout is getting applied to the accept operation because JSSSocketFactory.initializeSocket() has taken it upon itself to set the timeout. We can't set the connectionTimeout to 0 because the tomcat endpoint's only set timeout values > 0. Apparently this problem has been with us for a long time from looking at the change logs. I think the only reason it's showing up now with tomcat 6 is because the new tomcat code is now catching and reporting the exception in JIoEndpoint.run with these lines: }catch ( IOException x ) { if ( running ) log.error(sm.getString("endpoint.accept.fail"), x); } Bottom line, we can't fix this with a config file change, the socketAccept() must be fixed so it doesn't use the base timeout. We should at the same time fix the erroneous default timeout in JSSSocketFactory.initializeSocket(). I will attach another patch for that in a moment.
Created attachment 462479 [details] do not set default socket timeout in JSSSocketFactory.initializeSocket()
Used Cristina's first suggestion in comment #6, call setSoTimeout(0) to disable. Sending src/org/apache/tomcat/util/net/jss/JSSSocketFactory.java Transmitting file data . Committed revision 107.