Author: markt Date: Tue Sep 3 09:24:08 2013 New Revision: 1519611 URL: http://svn.apache.org/r1519611 Log: Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=55500 Ensure async timeout is applied when using Servlet 3.0 async with the AJP NIO connector.
Modified: tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java tomcat/trunk/java/org/apache/coyote/ajp/AjpAprProcessor.java tomcat/trunk/java/org/apache/coyote/ajp/AjpNioProcessor.java tomcat/trunk/java/org/apache/coyote/ajp/AjpProcessor.java Modified: tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java?rev=1519611&r1=1519610&r2=1519611&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java (original) +++ tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java Tue Sep 3 09:24:08 2013 @@ -473,6 +473,10 @@ public abstract class AbstractAjpProcess asyncStateMachine.asyncStart((AsyncContextCallback) param); } else if (actionCode == ActionCode.ASYNC_DISPATCHED) { asyncStateMachine.asyncDispatched(); + } else if (actionCode == ActionCode.ASYNC_SETTIMEOUT) { + if (param == null) return; + long timeout = ((Long)param).longValue(); + socketWrapper.setTimeout(timeout); } else if (actionCode == ActionCode.ASYNC_TIMEOUT) { AtomicBoolean result = (AtomicBoolean) param; result.set(asyncStateMachine.asyncTimeout()); @@ -556,6 +560,7 @@ public abstract class AbstractAjpProcess try { rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE); error = !getAdapter().asyncDispatch(request, response, status); + resetTimeouts(); } catch (InterruptedIOException e) { error = true; } catch (Throwable t) { @@ -806,6 +811,18 @@ public abstract class AbstractAjpProcess // Methods called by action() protected abstract void actionInternal(ActionCode actionCode, Object param); + // Methods called by asyncDispatch + /** + * Provides a mechanism for those connector implementations (currently only + * NIO) that need to reset timeouts from Async timeouts to standard HTTP + * timeouts once async processing completes. + */ + protected abstract void resetTimeouts(); + + // Methods called by prepareResponse() + protected abstract void output(byte[] src, int offset, int length) + throws IOException; + // Methods called by process() protected abstract void setupSocket(SocketWrapper<S> socketWrapper) throws IOException; @@ -813,10 +830,6 @@ public abstract class AbstractAjpProcess protected abstract void setTimeout(SocketWrapper<S> socketWrapper, int timeout) throws IOException; - // Methods called by prepareResponse() - protected abstract void output(byte[] src, int offset, int length) - throws IOException; - // Methods used by readMessage /** * Read at least the specified amount of bytes, and place them Modified: tomcat/trunk/java/org/apache/coyote/ajp/AjpAprProcessor.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/ajp/AjpAprProcessor.java?rev=1519611&r1=1519610&r2=1519611&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/ajp/AjpAprProcessor.java (original) +++ tomcat/trunk/java/org/apache/coyote/ajp/AjpAprProcessor.java Tue Sep 3 09:24:08 2013 @@ -89,10 +89,7 @@ public class AjpAprProcessor extends Abs ((AprEndpoint)endpoint).processSocketAsync(this.socketWrapper, SocketStatus.OPEN_READ); } - } else if (actionCode == ActionCode.ASYNC_SETTIMEOUT) { - if (param == null) return; - long timeout = ((Long)param).longValue(); - socketWrapper.setTimeout(timeout); + } else if (actionCode == ActionCode.ASYNC_DISPATCH) { if (asyncStateMachine.asyncDispatch()) { ((AprEndpoint)endpoint).processSocketAsync(this.socketWrapper, @@ -103,6 +100,13 @@ public class AjpAprProcessor extends Abs @Override + protected void resetTimeouts() { + // NO-OP. The AJP APR/native connector only uses the timeout value on + // time SocketWrapper for async timeouts. + } + + + @Override protected void setupSocket(SocketWrapper<Long> socketWrapper) { long socketRef = socketWrapper.getSocket().longValue(); Socket.setrbb(socketRef, inputBuffer); Modified: tomcat/trunk/java/org/apache/coyote/ajp/AjpNioProcessor.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/ajp/AjpNioProcessor.java?rev=1519611&r1=1519610&r2=1519611&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/ajp/AjpNioProcessor.java (original) +++ tomcat/trunk/java/org/apache/coyote/ajp/AjpNioProcessor.java Tue Sep 3 09:24:08 2013 @@ -26,7 +26,6 @@ import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.tomcat.util.net.NioChannel; import org.apache.tomcat.util.net.NioEndpoint; -import org.apache.tomcat.util.net.NioEndpoint.KeyAttachment; import org.apache.tomcat.util.net.NioSelectorPool; import org.apache.tomcat.util.net.SocketStatus; import org.apache.tomcat.util.net.SocketWrapper; @@ -74,14 +73,7 @@ public class AjpNioProcessor extends Abs ((NioEndpoint)endpoint).dispatchForEvent( socketWrapper.getSocket(), SocketStatus.OPEN_READ, true); } - } else if (actionCode == ActionCode.ASYNC_SETTIMEOUT) { - if (param == null) return; - long timeout = ((Long)param).longValue(); - final KeyAttachment ka = - (KeyAttachment)socketWrapper.getSocket().getAttachment(false); - if (keepAliveTimeout > 0) { - ka.setTimeout(timeout); - } + } else if (actionCode == ActionCode.ASYNC_DISPATCH) { if (asyncStateMachine.asyncDispatch()) { ((NioEndpoint)endpoint).dispatchForEvent( @@ -92,6 +84,27 @@ public class AjpNioProcessor extends Abs @Override + protected void resetTimeouts() { + // The NIO connector uses the timeout configured on the wrapper in the + // poller. Therefore, it needs to be reset once asycn processing has + // finished. + final NioEndpoint.KeyAttachment attach = (NioEndpoint.KeyAttachment)socketWrapper.getSocket().getAttachment(false); + if (!error && attach != null && + asyncStateMachine.isAsyncDispatching()) { + long soTimeout = endpoint.getSoTimeout(); + + //reset the timeout + if (keepAliveTimeout > 0) { + attach.setTimeout(keepAliveTimeout); + } else { + attach.setTimeout(soTimeout); + } + } + + } + + + @Override protected void setupSocket(SocketWrapper<NioChannel> socketWrapper) throws IOException { // NO-OP Modified: tomcat/trunk/java/org/apache/coyote/ajp/AjpProcessor.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/ajp/AjpProcessor.java?rev=1519611&r1=1519610&r2=1519611&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/ajp/AjpProcessor.java (original) +++ tomcat/trunk/java/org/apache/coyote/ajp/AjpProcessor.java Tue Sep 3 09:24:08 2013 @@ -86,11 +86,7 @@ public class AjpProcessor extends Abstra ((JIoEndpoint)endpoint).processSocketAsync(this.socketWrapper, SocketStatus.OPEN_READ); } - } else if (actionCode == ActionCode.ASYNC_SETTIMEOUT) { - if (param == null) return; - long timeout = ((Long)param).longValue(); - // if we are not piggy backing on a worker thread, set the timeout - socketWrapper.setTimeout(timeout); + } else if (actionCode == ActionCode.ASYNC_DISPATCH) { if (asyncStateMachine.asyncDispatch()) { ((JIoEndpoint)endpoint).processSocketAsync(this.socketWrapper, @@ -101,6 +97,13 @@ public class AjpProcessor extends Abstra @Override + protected void resetTimeouts() { + // NO-OP. The AJP BIO connector only uses the timeout value on the + // SocketWrapper for async timeouts. + } + + + @Override protected void setupSocket(SocketWrapper<Socket> socketWrapper) throws IOException { input = socketWrapper.getSocket().getInputStream(); --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org