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: [email protected]
For additional commands, e-mail: [email protected]