Author: markt Date: Tue Sep 6 15:00:02 2011 New Revision: 1165693 URL: http://svn.apache.org/viewvc?rev=1165693&view=rev Log: Aligning the HTTP connectors. Handle request line timeouts consistently Handle upload timeouts more consistently
Modified: tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java tomcat/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java Modified: tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java?rev=1165693&r1=1165692&r2=1165693&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java (original) +++ tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java Tue Sep 6 15:00:02 2011 @@ -96,6 +96,7 @@ public abstract class AbstractHttp11Proc */ protected boolean keptAlive; + /** * Flag that indicates that send file processing is in progress and that the * socket should not be returned to the poller (where a poller is used). @@ -816,6 +817,12 @@ public abstract class AbstractHttp11Proc /** + * Configures the timeout to be used for reading the request line. + */ + protected abstract void setRequestLineReadTimeout() throws IOException; + + + /** * After reading the request headers, we have to setup the request filters. */ protected void prepareRequest() { Modified: tomcat/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java?rev=1165693&r1=1165692&r2=1165693&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java (original) +++ tomcat/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java Tue Sep 6 15:00:02 2011 @@ -190,8 +190,6 @@ public class Http11AprProcessor extends keptAlive = socketWrapper.isKeptAlive(); } - int soTimeout = endpoint.getSoTimeout(); - if (disableKeepAlive()) { socketWrapper.setKeepAliveLeft(0); } @@ -203,9 +201,8 @@ public class Http11AprProcessor extends // Parsing the request header try { - if( !disableUploadTimeout && keptAlive && soTimeout > 0 ) { - Socket.timeoutSet(socketRef, soTimeout * 1000); - } + setRequestLineReadTimeout(); + if (!inputBuffer.parseRequestLine(keptAlive)) { // This means that no data is available right now // (long keepalive), so that the processor should be recycled @@ -326,6 +323,10 @@ public class Http11AprProcessor extends outputBuffer.nextRequest(); } + if (!disableUploadTimeout) { + Socket.timeoutSet(socketRef, endpoint.getSoTimeout() * 1000); + } + rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE); if (breakKeepAliveLoop(socketWrapper)) { @@ -358,6 +359,36 @@ public class Http11AprProcessor extends @Override + protected boolean disableKeepAlive() { + return false; + } + + + @Override + protected void setRequestLineReadTimeout() throws IOException { + // Timeouts while in the poller are handled entirely by the poller + // Only need to be concerned with socket timeouts + + // APR uses simulated blocking so if some request line data is present + // then it must all be presented (with the normal socket timeout). + + // When entering the processing loop for the first time there will + // always be some data to read so the keep-alive timeout is not required + + // For the second and subsequent executions of the processing loop, if + // there is no request line data present then no further data will be + // read from the socket. If there is request line data present then it + // must all be presented (with the normal socket timeout) + + // When the socket is created it is given the correct timeout. + // sendfile may change the timeout but will restore it + // This processor may change the timeout for uploads but will restore it + + // NO-OP + } + + + @Override protected void setCometTimeouts(SocketWrapper<Long> socketWrapper) { // NO-OP for APR/native return; @@ -393,12 +424,6 @@ public class Http11AprProcessor extends @Override - protected boolean disableKeepAlive() { - return false; - } - - - @Override protected void resetTimeouts() { // NOOP for APR } Modified: tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java?rev=1165693&r1=1165692&r2=1165693&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java (original) +++ tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java Tue Sep 6 15:00:02 2011 @@ -219,8 +219,6 @@ public class Http11NioProcessor extends keptAlive = socketWrapper.isKeptAlive(); } - int soTimeout = endpoint.getSoTimeout(); - if (disableKeepAlive()) { socketWrapper.setKeepAliveLeft(0); } @@ -228,13 +226,10 @@ public class Http11NioProcessor extends while (!error && keepAlive && !comet && !isAsync() && !endpoint.isPaused()) { - //always default to our soTimeout - socketWrapper.setTimeout(soTimeout); // Parsing the request header try { - if( !disableUploadTimeout && keptAlive && soTimeout > 0 ) { - socketWrapper.getSocket().getIOChannel().socket().setSoTimeout(soTimeout); - } + setRequestLineReadTimeout(); + if (!inputBuffer.parseRequestLine(keptAlive)) { // Haven't finished reading the request so keep the socket // open @@ -372,6 +367,11 @@ public class Http11NioProcessor extends outputBuffer.nextRequest(); } + if (!disableUploadTimeout) { //only for body, not for request headers + socketWrapper.getSocket().getIOChannel().socket().setSoTimeout( + endpoint.getSoTimeout()); + } + rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE); if (breakKeepAliveLoop(socketWrapper)) { @@ -404,6 +404,33 @@ public class Http11NioProcessor extends @Override + protected boolean disableKeepAlive() { + return false; + } + + + @Override + protected void setRequestLineReadTimeout() throws IOException { + // socket.setTimeout() + // - timeout used by poller + // socket.getSocket().getIOChannel().socket().setSoTimeout() + // - timeout used for blocking reads + + // When entering the processing loop there will always be data to read + // so no point changing timeouts at this point + + // For the second and subsequent executions of the processing loop, a + // non-blocking read is used so again no need to set the timeouts + + // Because NIO supports non-blocking reading of the request line and + // headers the timeouts need to be set when returning the socket to + // the poller rather than here. + + // NO-OP + } + + + @Override protected void setCometTimeouts(SocketWrapper<NioChannel> socketWrapper) { // Comet support SelectionKey key = socketWrapper.getSocket().getIOChannel().keyFor( @@ -440,12 +467,6 @@ public class Http11NioProcessor extends @Override - protected boolean disableKeepAlive() { - return false; - } - - - @Override public void recycleInternal() { socket = null; cometClose = false; Modified: tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java?rev=1165693&r1=1165692&r2=1165693&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java (original) +++ tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java Tue Sep 6 15:00:02 2011 @@ -165,48 +165,8 @@ public class Http11Processor extends Abs // Parsing the request header try { - int standardTimeout = 0; - if (keptAlive) { - if (keepAliveTimeout > 0) { - standardTimeout = keepAliveTimeout; - } else if (soTimeout > 0) { - standardTimeout = soTimeout; - } - } - /* - * When there is no data in the buffer and this is not the first - * request on this connection and timeouts are being used the - * first read for this request may need a different timeout to - * take account of time spent waiting for a processing thread. - * - * This is a little hacky but better than exposing the socket - * and the timeout info to the InputBuffer - */ - if (inputBuffer.lastValid == 0 && - socketWrapper.getLastAccess() > -1 && - standardTimeout > 0) { - - long queueTime = System.currentTimeMillis() - - socketWrapper.getLastAccess(); - int firstReadTimeout; - if (queueTime >= standardTimeout) { - // Queued for longer than timeout but there might be - // data so use shortest possible timeout - firstReadTimeout = 1; - } else { - // Cast is safe since queueTime must be less than - // standardTimeout which is an int - firstReadTimeout = standardTimeout - (int) queueTime; - } - socket.getSocket().setSoTimeout(firstReadTimeout); - if (!inputBuffer.fill()) { - throw new EOFException(sm.getString("iib.eof.error")); - } - } - if (standardTimeout > 0) { - socket.getSocket().setSoTimeout(standardTimeout); - } - + setRequestLineReadTimeout(); + inputBuffer.parseRequestLine(false); if (endpoint.isPaused()) { // 503 - Service unavailable @@ -320,6 +280,10 @@ public class Http11Processor extends Abs outputBuffer.nextRequest(); } + if (!disableUploadTimeout) { + socket.getSocket().setSoTimeout(endpoint.getSoTimeout()); + } + rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE); if (breakKeepAliveLoop(socketWrapper)) { @@ -352,24 +316,6 @@ public class Http11Processor extends Abs @Override - protected void setCometTimeouts(SocketWrapper<Socket> socketWrapper) { - // NO-OP for BIO - return; - } - - - @Override - protected boolean breakKeepAliveLoop(SocketWrapper<Socket> socketWrapper) { - // If we don't have a pipe-lined request allow this thread to be - // used by another connection - if (inputBuffer.lastValid == 0) { - return true; - } - return false; - } - - - @Override protected boolean disableKeepAlive() { int threadRatio = -1; // These may return zero or negative values @@ -390,6 +336,70 @@ public class Http11Processor extends Abs @Override + protected void setRequestLineReadTimeout() throws IOException { + + int standardTimeout = 0; + + if (keptAlive) { + if (keepAliveTimeout > 0) { + standardTimeout = keepAliveTimeout; + } else if (endpoint.getSoTimeout() > 0) { + standardTimeout = endpoint.getSoTimeout(); + } + } + /* + * When there is no data in the buffer and this is not the first + * request on this connection and timeouts are being used the + * first read for this request may need a different timeout to + * take account of time spent waiting for a processing thread. + * + * This is a little hacky but better than exposing the socket + * and the timeout info to the InputBuffer + */ + if (inputBuffer.lastValid == 0 && socket.getLastAccess() > -1 && + standardTimeout > 0) { + + long queueTime = System.currentTimeMillis() - socket.getLastAccess(); + int firstReadTimeout; + if (queueTime >= standardTimeout) { + // Queued for longer than timeout but there might be + // data so use shortest possible timeout + firstReadTimeout = 1; + } else { + // Cast is safe since queueTime must be less than + // standardTimeout which is an int + firstReadTimeout = standardTimeout - (int) queueTime; + } + socket.getSocket().setSoTimeout(firstReadTimeout); + if (!inputBuffer.fill()) { + throw new EOFException(sm.getString("iib.eof.error")); + } + // Once the first byte has been read, the standard timeout should be + // used so restore it here. + socket.getSocket().setSoTimeout(endpoint.getSoTimeout()); + } + } + + + @Override + protected void setCometTimeouts(SocketWrapper<Socket> socketWrapper) { + // NO-OP for BIO + return; + } + + + @Override + protected boolean breakKeepAliveLoop(SocketWrapper<Socket> socketWrapper) { + // If we don't have a pipe-lined request allow this thread to be + // used by another connection + if (inputBuffer.lastValid == 0) { + return true; + } + return false; + } + + + @Override protected void resetTimeouts() { // NOOP for BIO } Modified: tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java?rev=1165693&r1=1165692&r2=1165693&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java Tue Sep 6 15:00:02 2011 @@ -752,8 +752,7 @@ public class AprEndpoint extends Abstrac Socket.optSet(socket, Socket.APR_SO_LINGER, socketProperties.getSoLingerTime()); if (socketProperties.getTcpNoDelay()) Socket.optSet(socket, Socket.APR_TCP_NODELAY, (socketProperties.getTcpNoDelay() ? 1 : 0)); - if (socketProperties.getSoTimeout() > 0) - Socket.timeoutSet(socket, socketProperties.getSoTimeout() * 1000); + Socket.timeoutSet(socket, socketProperties.getSoTimeout() * 1000); // 2: SSL handshake step = 2; --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org