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