Bug 655915

Summary: connectionTimeout incorrectly applied to socket accept operation
Product: [Retired] Dogtag Certificate System Reporter: John Dennis <jdennis>
Component: JSSAssignee: Christina Fu <cfu>
Status: CLOSED EOL QA Contact: Ben Levenson <benl>
Severity: medium Docs Contact:
Priority: medium    
Version: unspecifiedCC: alee, dpal, jgalipea, mharmsen, rrelyea
Target Milestone: ---   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2020-03-27 18:37:19 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
Original comment without whitespace mangling for easier reading
none
patch fixing timeout parameter to acceptSocket
jdennis: review? (cfu)
do not set default socket timeout in JSSSocketFactory.initializeSocket() jdennis: review? (cfu)

Description John Dennis 2010-11-22 17:08:46 UTC
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);

Comment 1 John Dennis 2010-11-22 17:12:24 UTC
Created attachment 462081 [details]
Original comment without whitespace mangling for easier reading

Comment 2 John Dennis 2010-11-22 17:13:36 UTC
Created attachment 462082 [details]
patch fixing timeout parameter to acceptSocket

Comment 4 John Dennis 2010-11-23 22:27:42 UTC
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.

Comment 5 John Dennis 2010-11-23 22:50:47 UTC
Created attachment 462479 [details]
do not set default socket timeout in JSSSocketFactory.initializeSocket()

Comment 7 John Dennis 2010-12-29 15:07:44 UTC
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.