Author: markt
Date: Mon Jun 12 18:42:32 2017
New Revision: 1798509
URL: http://svn.apache.org/viewvc?rev=1798509&view=rev
Log:
Make asynchronous error handling more robust. In particular ensure that
onError() is called for any registered AsyncListeners after an I/O error on a
non-container thread.
Modified:
tomcat/trunk/conf/logging.properties
tomcat/trunk/java/org/apache/coyote/AbstractProcessor.java
tomcat/trunk/java/org/apache/coyote/AsyncStateMachine.java
tomcat/trunk/webapps/docs/changelog.xml
Modified: tomcat/trunk/conf/logging.properties
URL:
http://svn.apache.org/viewvc/tomcat/trunk/conf/logging.properties?rev=1798509&r1=1798508&r2=1798509&view=diff
==============================================================================
--- tomcat/trunk/conf/logging.properties (original)
+++ tomcat/trunk/conf/logging.properties Mon Jun 12 18:42:32 2017
@@ -65,6 +65,8 @@ org.apache.catalina.core.ContainerBase.[
# To see debug messages for HTTP/2 handling, uncomment the following line:
#org.apache.coyote.http2.level = FINE
+org.apache.coyote.level = FINEST
+org.apache.catalina.level = FINEST
# To see debug messages for WebSocket handling, uncomment the following line:
#org.apache.tomcat.websocket.level = FINE
Modified: tomcat/trunk/java/org/apache/coyote/AbstractProcessor.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/AbstractProcessor.java?rev=1798509&r1=1798508&r2=1798509&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/AbstractProcessor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/AbstractProcessor.java Mon Jun 12
18:42:32 2017
@@ -95,6 +95,7 @@ public abstract class AbstractProcessor
// have been completed. Dispatch to a container thread to do the
// clean-up. Need to do it this way to ensure that all the
necessary
// clean-up is performed.
+ asyncStateMachine.asyncMustError();
getLog().info(sm.getString("abstractProcessor.nonContainerThreadError"), t);
processSocketEvent(SocketEvent.ERROR, true);
}
Modified: tomcat/trunk/java/org/apache/coyote/AsyncStateMachine.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/AsyncStateMachine.java?rev=1798509&r1=1798508&r2=1798509&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/AsyncStateMachine.java [UTF-8]
(original)
+++ tomcat/trunk/java/org/apache/coyote/AsyncStateMachine.java [UTF-8] Mon Jun
12 18:42:32 2017
@@ -66,38 +66,49 @@ import org.apache.tomcat.util.security.P
* differences required to avoid race conditions during
error
* handling.
* DISPATCHING - The dispatch is being processed.
+ * MUST_ERROR - ServletRequest.startAsync() has been called followed by
an
+ * I/O error on a non-container thread. The main purpose of
+ * this state is to prevent additional async actions
+ * (complete(), dispatch() etc.) on the non-container
thread.
+ * The container will perform the necessary error handling,
+ * including ensuring that the AsyncLister.onError() method
+ * is called.
* ERROR - Something went wrong.
*
- * |-----------------»------|
- * | \|/
/---«-------------------------------«------------------------------|
- * | |----------«-----E R R O
R--«-----------------------«-------------------------------| |
- * | | complete() /|\/|\\ \-«--------------------------------«-------|
| |
- * | | | | \ |
| |
- * | | |-----»-------| | \-----------»----------| |
| |
- * | | | | |dispatch() |
| |
- * | | | | \|/ ^
| |
- * | | | | |--|timeout() | |
| |
- * | | | post() | | \|/ | post() |
| |
- * | | | |---------- | --»DISPATCHED«---------- |
--------------COMPLETING«-----| | |
- * | | | | | /|\/|\ | | | /|\
/|\ | | |
- * | | | | |---»- | ---| | |startAsync() | timeout()|--|
| | | |
- * | | ^ ^ | | | | |
| | ^ |
- * | | | | | |-- \ -----| | complete() |
|post() | | |
- * | | | | | | \ | /--»----- |
---COMPLETE_PENDING-»-| ^ | |
- * | | | | | | \ | / |
| | |
- * | | | | | ^ \ | / |
| | |
- * | \|/ | | | | \ \|/ / post() |
complete() | | |
- * | MUST_COMPLETE-«- | - | --«----STARTING--»--------- | ------------|
/---»-----| | |
- * | /|\ /|\ | | complete() | \ | | /
| ^
- * | | | | | | \ | post() | /
error() | |
- * | | | ^ | dispatch()| \ | |-----| |
//------»-------| |
- * | | | | | | \ | | | | //
|
- * | | | | | \|/ \ | | \|/\|/ //
post() |
+ *
|-----«-------------------------------«------------------------------|
+ * |
|
+ * | error()
|
+ * |-----------------»---| |
|--«--------MUST_ERROR---------------«------------------------| |
+ * | \|/ \|/\|/
| |
+ * | |----------«-----E R R O
R--«-----------------------«-------------------------------| | |
+ * | | complete() /|\/|\\ \-«--------------------------------«-------|
| | |
+ * | | | | \ |
| | |
+ * | | |-----»-------| | \-----------»----------| |
| | |
+ * | | | | |dispatch() |
| ^ |
+ * | | | | \|/ ^
| | |
+ * | | | | |--|timeout() | |
| | |
+ * | | | post() | | \|/ | post() |
| | |
+ * | | | |---------- | --»DISPATCHED«---------- |
--------------COMPLETING«-----| | | |
+ * | | | | | /|\/|\ | | | /|\
/|\ | | | |
+ * | | | | |---»- | ---| | |startAsync() | timeout()|--|
| | | | |
+ * | | ^ ^ | | | | |
| | ^ | |
+ * | | | | | |-- \ -----| | complete() |
|post() | | | |
+ * | | | | | | \ | /--»----- |
---COMPLETE_PENDING-»-| ^ | | |
+ * | | | | | | \ | / |
| | | |
+ * | | | | | ^ \ | / |
complete() | | | |
+ * | \|/ | | | | \ \|/ / post() |
/---»-----| | ^ |
+ * | MUST_COMPLETE-«- | - | --«----STARTING--»--------- | ------------| /
| | |
+ * | /|\ /|\ | | complete() | \ | | /
error() | | ^
+ * | | | | | | \ | |
//---»----------| | |
+ * | | | ^ | dispatch()| \ | post() | //
| |
+ * | | | | | | \ | |-----| | //
nct-io-error | |
+ * | | | | | | \ | | | |
///---»---------------| |
+ * | | | | | \|/ \ | | \|/\| |||
|
* | | | | |--«--MUST_DISPATCH-----«-----|
|--«--STARTED«---------«---------| |
- * | | | | dispatched() /|\ | \ / | |
| |
- * | | | | | | \ / | |
| |
- * | | | | | | \ / | |
| |
- * | | | | | |post() \ | | |
^ |
+ * | | | | dispatched() /|\ | \ / | |
post() | |
+ * | | | | | | \ / | |
| |
+ * | | | | | | \ / | |
| |
+ * | | | | | |post() | | | |
^ |
* ^ | ^ | | | \|/ | |
|asyncOperation() | |
* | | | ^ | | DISPATCH_PENDING | | |
| |
* | | | | | | |post() | | |
| |
@@ -142,6 +153,7 @@ public class AsyncStateMachine {
DISPATCH_PENDING(true, true, false, false),
DISPATCHING (true, false, false, true),
READ_WRITE_OP (true, true, false, false),
+ MUST_ERROR (true, true, false, false),
ERROR (true, true, false, false);
private final boolean isAsync;
@@ -384,6 +396,18 @@ public class AsyncStateMachine {
}
+ public synchronized void asyncMustError() {
+ if (state == AsyncState.STARTED) {
+ clearNonBlockingListeners();
+ state = AsyncState.MUST_ERROR;
+ } else {
+ throw new IllegalStateException(
+ sm.getString("asyncStateMachine.invalidAsyncState",
+ "asyncMustError()", state));
+ }
+ }
+
+
public synchronized void asyncError() {
if (state == AsyncState.STARTING ||
state == AsyncState.STARTED ||
@@ -391,7 +415,8 @@ public class AsyncStateMachine {
state == AsyncState.TIMING_OUT ||
state == AsyncState.MUST_COMPLETE ||
state == AsyncState.READ_WRITE_OP ||
- state == AsyncState.COMPLETING) {
+ state == AsyncState.COMPLETING ||
+ state == AsyncState.MUST_ERROR) {
clearNonBlockingListeners();
state = AsyncState.ERROR;
} else {
Modified: tomcat/trunk/webapps/docs/changelog.xml
URL:
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1798509&r1=1798508&r2=1798509&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Mon Jun 12 18:42:32 2017
@@ -117,6 +117,12 @@
changed the status code recorded in the access log when the client
dropped the connection from 200 to 500. (markt)
</fix>
+ <fix>
+ Make asynchronous error handling more robust. In particular ensure that
+ <code>onError()</code> is called for any registered
+ <code>AsyncListener</code>s after an I/O error on a non-container
+ thread. (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Jasper">
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]