Author: markt
Date: Fri Dec  5 09:36:12 2014
New Revision: 1643210

URL: http://svn.apache.org/viewvc?rev=1643210&view=rev
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=57252
Provide application configured error pages with a chance to handle an
async error before the built-in error reporting.

Modified:
    tomcat/trunk/java/org/apache/catalina/core/StandardHostValve.java
    tomcat/trunk/java/org/apache/catalina/valves/ErrorReportValve.java

Modified: tomcat/trunk/java/org/apache/catalina/core/StandardHostValve.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/StandardHostValve.java?rev=1643210&r1=1643209&r2=1643210&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/StandardHostValve.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/StandardHostValve.java Fri Dec  
5 09:36:12 2014
@@ -120,9 +120,6 @@ final class StandardHostValve extends Va
 
         boolean asyncAtStart = request.isAsync();
         boolean asyncDispatching = request.isAsyncDispatching();
-        // An async error page may dispatch to another resource. This flag 
helps
-        // ensure an infinite error handling loop is not entered
-        boolean errorAtStart = response.isError();
 
         try {
             context.bind(Globals.IS_SECURITY_ENABLED, MY_CLASSLOADER);
@@ -135,18 +132,26 @@ final class StandardHostValve extends Va
                 return;
             }
 
-            // Ask this Context to process this request
+            // Ask this Context to process this request. Requests that are in
+            // async mode and are not being dispatched to this resource must be
+            // in error and have been routed here to check for application
+            // defined error pages.
             try {
                 if (!asyncAtStart || asyncDispatching) {
                     context.getPipeline().getFirst().invoke(request, response);
                 } else {
-                    if (!errorAtStart) {
+                    // Make sure this request/response is here because an error
+                    // report is required.
+                    if (!response.isErrorReportRequired()) {
                         throw new 
IllegalStateException(sm.getString("standardHost.asyncStateError"));
                     }
                 }
             } catch (Throwable t) {
                 ExceptionUtils.handleThrowable(t);
-                if (errorAtStart) {
+                // If a new error occurred while trying to report a previous
+                // error simply log the new error and allow the original error
+                // to be reported.
+                if (response.isErrorReportRequired()) {
                     container.getLogger().error("Exception Processing " +
                             request.getRequestURI(), t);
                 } else {
@@ -157,28 +162,27 @@ final class StandardHostValve extends Va
 
             Throwable t = (Throwable) 
request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
 
-            // If the request was async at the start and an error occurred
-            // then the async error handling will kick-in and that will fire
-            // the request destroyed event *after* the error handling has
-            // taken place.
-            if (!(request.isAsync() || (asyncAtStart && t != null))) {
-                // Protect against NPEs if context was destroyed during a
-                // long running request.
-                if (context.getState().isAvailable()) {
-                    if (!errorAtStart) {
-                        // Error page processing
-                        response.setSuspended(false);
-
-                        if (t != null) {
-                            throwable(request, response, t);
-                        } else {
-                            status(request, response);
-                        }
-                    }
+            // Protect against NPEs if the context was destroyed during a
+            // long running request.
+            if (!context.getState().isAvailable()) {
+                return;
+            }
+
+            // Look for (and render if found) an application level error page
+            if (response.isErrorReportRequired()) {
+                // Error page processing
+                response.setSuspended(false);
 
-                    context.fireRequestDestroyEvent(request);
+                if (t != null) {
+                    throwable(request, response, t);
+                } else {
+                    status(request, response);
                 }
             }
+
+            if (!request.isAsync() && !response.isErrorReportRequired()) {
+                context.fireRequestDestroyEvent(request);
+            }
         } finally {
             // Access a session (if present) to update last accessed time, 
based
             // on a strict interpretation of the specification

Modified: tomcat/trunk/java/org/apache/catalina/valves/ErrorReportValve.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/valves/ErrorReportValve.java?rev=1643210&r1=1643209&r2=1643210&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/valves/ErrorReportValve.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/valves/ErrorReportValve.java Fri Dec  
5 09:36:12 2014
@@ -97,8 +97,10 @@ public class ErrorReportValve extends Va
 
         Throwable throwable = (Throwable) 
request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
 
-        if (request.isAsyncStarted() && ((response.getStatus() < 400 &&
-                throwable == null) || request.isAsyncDispatching())) {
+        // If an async request is in progress and is not going to end once this
+        // container thread finishes, do not trigger error page handling - it
+        // will be triggered later if required.
+        if (request.isAsync() && !request.isAsyncCompleting()) {
             return;
         }
 
@@ -122,11 +124,6 @@ public class ErrorReportValve extends Va
         } catch (Throwable tt) {
             ExceptionUtils.handleThrowable(tt);
         }
-
-        if (request.isAsyncStarted() && !request.isAsyncCompleting() &&
-                !request.isAsyncDispatching()) {
-            request.getAsyncContext().complete();
-        }
     }
 
 



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

Reply via email to