Author: markt
Date: Fri Dec  5 09:48:24 2014
New Revision: 1643215

URL: http://svn.apache.org/viewvc?rev=1643215&view=rev
Log: (empty)

Modified:
    tomcat/tc8.0.x/trunk/   (props changed)
    tomcat/tc8.0.x/trunk/java/org/apache/coyote/AsyncStateMachine.java
    tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml

Propchange: tomcat/tc8.0.x/trunk/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri Dec  5 09:48:24 2014
@@ -1 +1 @@
-/tomcat/trunk:1636524,1637156,1637176,1637188,1637331,1637684,1637695,1638720-1638725,1639653,1640010,1640084,1640088,1640275,1640322,1640347,1640361,1640365,1640403,1640410,1640652,1640655-1640658,1640688,1640700-1640883,1640903,1640976,1640978,1641000,1641026,1641038-1641039,1641051-1641052,1641058,1641064,1641300,1641369,1641374,1641380,1641486,1641634,1641656-1641692,1641704,1641707-1641718,1641720-1641722,1641735,1641981,1642668,1642679,1642697,1642699,1643066,1643121
+/tomcat/trunk:1636524,1637156,1637176,1637188,1637331,1637684,1637695,1638720-1638725,1639653,1640010,1640084,1640088,1640275,1640322,1640347,1640361,1640365,1640403,1640410,1640652,1640655-1640658,1640688,1640700-1640883,1640903,1640976,1640978,1641000,1641026,1641038-1641039,1641051-1641052,1641058,1641064,1641300,1641369,1641374,1641380,1641486,1641634,1641656-1641692,1641704,1641707-1641718,1641720-1641722,1641735,1641981,1642668,1642679,1642697,1642699,1643002,1643066,1643121

Modified: tomcat/tc8.0.x/trunk/java/org/apache/coyote/AsyncStateMachine.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/coyote/AsyncStateMachine.java?rev=1643215&r1=1643214&r2=1643215&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/coyote/AsyncStateMachine.java [UTF-8] 
(original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/coyote/AsyncStateMachine.java [UTF-8] 
Fri Dec  5 09:48:24 2014
@@ -106,28 +106,30 @@ public class AsyncStateMachine {
         StringManager.getManager(Constants.Package);
 
     private static enum AsyncState {
-        DISPATCHED(false, false, false, false),
-        STARTING(true, true, false, false),
-        STARTED(true, true, false, false),
-        MUST_COMPLETE(true, true, true, false),
-        COMPLETING(true, false, true, false),
-        TIMING_OUT(true, false, false, false),
-        MUST_DISPATCH(true, true, false, true),
-        DISPATCHING(true, false, false, true),
-        READ_WRITE_OP(true, true, false, false),
-        ERROR(true, false, false, false);
+        DISPATCHED(false, false, false, false, false),
+        STARTING(true, true, false, false, true),
+        STARTED(true, true, false, false, false),
+        MUST_COMPLETE(true, true, true, false, false),
+        COMPLETING(true, false, true, false, false),
+        TIMING_OUT(true, false, false, false, false),
+        MUST_DISPATCH(true, true, false, true, true),
+        DISPATCHING(true, false, false, true, false),
+        READ_WRITE_OP(true, true, false, false, true),
+        ERROR(true, false, false, false, false);
 
         private final boolean isAsync;
         private final boolean isStarted;
         private final boolean isCompleting;
         private final boolean isDispatching;
+        private final boolean pauseNonContainerThread;
 
         private AsyncState(boolean isAsync, boolean isStarted, boolean 
isCompleting,
-                boolean isDispatching) {
+                boolean isDispatching, boolean pauseNonContainerThread) {
             this.isAsync = isAsync;
             this.isStarted = isStarted;
             this.isCompleting = isCompleting;
             this.isDispatching = isDispatching;
+            this.pauseNonContainerThread = pauseNonContainerThread;
         }
 
         public boolean isAsync() {
@@ -145,6 +147,10 @@ public class AsyncStateMachine {
         public boolean isCompleting() {
             return isCompleting;
         }
+
+        public boolean getPauseNonContainerThread() {
+            return pauseNonContainerThread;
+        }
     }
 
 
@@ -211,6 +217,12 @@ public class AsyncStateMachine {
      */
     public synchronized SocketState asyncPostProcess() {
 
+        // Unpause any non-container threads that may be waiting for this
+        // container thread to complete this method. Note because of the syncs
+        // those non-container threads won't start back up until until this
+        // method exits.
+        notifyAll();
+
         if (state == AsyncState.STARTING || state == AsyncState.READ_WRITE_OP) 
{
             state = AsyncState.STARTED;
             return SocketState.LONG;
@@ -241,8 +253,8 @@ public class AsyncStateMachine {
 
 
     public synchronized boolean asyncComplete() {
+        pauseNonContainerThread();
         boolean doComplete = false;
-
         if (state == AsyncState.STARTING) {
             state = AsyncState.MUST_COMPLETE;
         } else if (state == AsyncState.STARTED) {
@@ -282,6 +294,7 @@ public class AsyncStateMachine {
 
 
     public synchronized boolean asyncDispatch() {
+        pauseNonContainerThread();
         boolean doDispatch = false;
         if (state == AsyncState.STARTING) {
             state = AsyncState.MUST_DISPATCH;
@@ -377,4 +390,24 @@ public class AsyncStateMachine {
         processor.getRequest().listener = null;
         processor.getRequest().getResponse().listener = null;
     }
+
+
+    /*
+     * startAsync() has been called but the container thread where this was
+     * called has not completed processing. To avoid various race conditions -
+     * including several related to error page handling - pause this
+     * non-container thread until the container thread has finished processing.
+     * The non-container thread will be paused until the container thread
+     * completes asyncPostProcess().
+     */
+    private synchronized void pauseNonContainerThread() {
+        while (!ContainerThreadMarker.isContainerThread() &&
+                state.getPauseNonContainerThread()) {
+            try {
+                wait();
+            } catch (InterruptedException e) {
+                // TODO Log this?
+            }
+        }
+    }
 }

Modified: tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml?rev=1643215&r1=1643214&r2=1643215&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml Fri Dec  5 09:48:24 2014
@@ -93,6 +93,11 @@
       <fix>
         Fix closing of Jars during annotation scanning. (schultz/kkolinko)
       </fix>
+      <fix>
+        Fix a concurrency issue in async processing. Ensure that a 
non-container
+        thread can not change the async state until the container thread has
+        completed. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Coyote">



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to