Author: markt Date: Mon Aug 17 07:28:18 2015 New Revision: 1696199 URL: http://svn.apache.org/r1696199 Log: Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=58157 Ensure that the handling of async timeouts does not result in an unnecessary dispatch to a container thread that could result in the current socket being added to the Poller multiple times and multiple attempts to process the same event for the same socket.
Modified: tomcat/trunk/java/org/apache/coyote/AsyncStateMachine.java Modified: tomcat/trunk/java/org/apache/coyote/AsyncStateMachine.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/AsyncStateMachine.java?rev=1696199&r1=1696198&r2=1696199&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/AsyncStateMachine.java [UTF-8] (original) +++ tomcat/trunk/java/org/apache/coyote/AsyncStateMachine.java [UTF-8] Mon Aug 17 07:28:18 2015 @@ -73,20 +73,20 @@ import org.apache.tomcat.util.security.P * | | | | | | | /-----------| | * | | | ^ |dispatch() | | / | * | | | | | | | / | - * | | | | \|/ / \|/ / postProcess() | - * | | | | MUST_DISPATCH / STARTED«---------«---------| | - * | | | | | / / | | | | - * | | | | |postProcess() / / | | ^ | - * ^ | ^ | | / / | |asyncOperation() | | - * | | | | | / / | | | | - * | | | | | |---------- / ----------/ | |--READ_WRITE_OP--»---| | - * | | | | | | / dispatch() | | | | | - * | | | | | | |-----/ auto| | | | error()| - * | | | | auto \|/ \|/ \|/ | dispatch()| | |-»--------| - * | | | |---«------DISPATCHING«--------«------------- | ------«----| | - * | | | /|\ | | + * | | | | \|/ | \|/ / postProcess() | + * | | | |----«----MUST_DISPATCH-----«-----| STARTED«---------«---------| | + * | | | | auto /|\ / | | | | + * | | | | | / | | ^ | + * ^ | ^ | | / | |asyncOperation() | | + * | | | ^ | / | | | | + * | | | | | |-------------/ | |--READ_WRITE_OP--»---| | + * | | | | | | dispatch() | | | | | + * | | | | | | auto| | | | error()| + * | | | | auto | \|/ | dispatch()| | |-»--------| + * | | | |---«---------- | ---DISPATCHING«-----«------ | ------«----| | + * | | | | | | * | | | | dispatch() \|/ | - * | | | |-----------------------TIMING_OUT | + * | | | |-----------«-----------TIMING_OUT | * | | | | | | * | | |-------«----------------------------------«------| | | * | | complete() | | @@ -296,7 +296,11 @@ public class AsyncStateMachine { public synchronized boolean asyncDispatch() { pauseNonContainerThread(); boolean doDispatch = false; - if (state == AsyncState.STARTING) { + if (state == AsyncState.STARTING || + state == AsyncState.TIMING_OUT || + state == AsyncState.ERROR) { + // In these three cases processing is on a container thread so no + // need to transfer processing to a new container thread state = AsyncState.MUST_DISPATCH; } else if (state == AsyncState.STARTED) { state = AsyncState.DISPATCHING; @@ -307,9 +311,7 @@ public class AsyncStateMachine { // request/response associated with the AsyncContext so need a new // container thread to process the different request/response. doDispatch = true; - } else if (state == AsyncState.READ_WRITE_OP || - state == AsyncState.TIMING_OUT || - state == AsyncState.ERROR) { + } else if (state == AsyncState.READ_WRITE_OP) { state = AsyncState.DISPATCHING; // If on a container thread then the socket will be added to the // poller poller when the thread exits the @@ -328,7 +330,8 @@ public class AsyncStateMachine { public synchronized void asyncDispatched() { - if (state == AsyncState.DISPATCHING) { + if (state == AsyncState.DISPATCHING || + state == AsyncState.MUST_DISPATCH) { state = AsyncState.DISPATCHED; } else { throw new IllegalStateException( --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org