From: markt Date: Wed, 29 Jun 2011 12:57:50 +0000 (+0000) Subject: Ensure that if asyncDispatch() is called during an onTimeout event and the target... X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=c63fb241150facd4d6de52a0c741b0af35fc87ce;p=tomcat7.0 Ensure that if asyncDispatch() is called during an onTimeout event and the target Servlet does not call startAsync() or complete() that Tomcat calls complete() (or does the equivalent) once the target Servlet exits. git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@1141079 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/java/org/apache/catalina/core/AsyncContextImpl.java b/java/org/apache/catalina/core/AsyncContextImpl.java index 2e6d6e0ca..33c6fb1e0 100644 --- a/java/org/apache/catalina/core/AsyncContextImpl.java +++ b/java/org/apache/catalina/core/AsyncContextImpl.java @@ -312,6 +312,9 @@ public class AsyncContextImpl implements AsyncContext, AsyncContextCallback { } try { dispatch.run(); + if (!request.isAsync()) { + fireOnComplete(); + } } catch (RuntimeException x) { // doInternalComplete(true); if (x.getCause() instanceof ServletException) { diff --git a/test/org/apache/catalina/core/TestAsyncContextImpl.java b/test/org/apache/catalina/core/TestAsyncContextImpl.java index 9a7273a93..146375c21 100644 --- a/test/org/apache/catalina/core/TestAsyncContextImpl.java +++ b/test/org/apache/catalina/core/TestAsyncContextImpl.java @@ -365,18 +365,26 @@ public class TestAsyncContextImpl extends TomcatBaseTest { } } - public void testTimeoutListenerComplete() throws Exception { + public void testTimeoutListenerCompleteNoDispatch() throws Exception { + // Should work doTestTimeout(true, null); } - public void testTimeoutListenerNoComplete() throws Exception { + public void testTimeoutListenerNoCompleteNoDispatch() throws Exception { + // Should trigger an error - must do one or other doTestTimeout(false, null); } - public void testTimeoutListenerDispatch() throws Exception { + public void testTimeoutListenerCompleteDispatch() throws Exception { + // Should trigger an error - can't do both doTestTimeout(true, "/nonasync"); } - + + public void testTimeoutListenerNoCompleteDispatch() throws Exception { + // Should work + doTestTimeout(false, "/nonasync"); + } + private void doTestTimeout(boolean completeOnTimeout, String dispatchUrl) throws Exception { @@ -413,23 +421,44 @@ public class TestAsyncContextImpl extends TomcatBaseTest { ctx.getPipeline().addValve(alv); tomcat.start(); - ByteChunk res = getUrl("http://localhost:" + getPort() + "/async"); + ByteChunk res = new ByteChunk(); + try { + getUrl("http://localhost:" + getPort() + "/async", res, null); + } catch (IOException ioe) { + // Ignore - expected for some error conditions + } StringBuilder expected = new StringBuilder("requestInitialized-"); expected.append("TimeoutServletGet-onTimeout-"); - if (!completeOnTimeout) { - expected.append("onError-"); - } - if (dispatchUrl == null) { - expected.append("onComplete-"); + if (completeOnTimeout) { + if (dispatchUrl == null) { + expected.append("onComplete-"); + expected.append("requestDestroyed"); + } else { + // Error - no further output + // There is no onComplete- since the complete event would be + // fired during post processing but since there is an error that + // never happens. + } } else { - expected.append("NonAsyncServletGet-"); + if (dispatchUrl == null) { + expected.append("onError-"); + } else { + expected.append("NonAsyncServletGet-"); + } + expected.append("onComplete-"); + expected.append("requestDestroyed"); } - expected.append("requestDestroyed"); assertEquals(expected.toString(), res.toString()); // Check the access log - validateAccessLog(alv, 1, 200, TimeoutServlet.ASYNC_TIMEOUT, - TimeoutServlet.ASYNC_TIMEOUT + TIMEOUT_MARGIN + REQUEST_TIME); + if (completeOnTimeout && dispatchUrl != null) { + validateAccessLog(alv, 1, 500, 0, TimeoutServlet.ASYNC_TIMEOUT + + TIMEOUT_MARGIN + REQUEST_TIME); + } else { + validateAccessLog(alv, 1, 200, TimeoutServlet.ASYNC_TIMEOUT, + TimeoutServlet.ASYNC_TIMEOUT + TIMEOUT_MARGIN + + REQUEST_TIME); + } } private static class TimeoutServlet extends HttpServlet { @@ -695,11 +724,10 @@ public class TestAsyncContextImpl extends TomcatBaseTest { resp.getWriter().write("onTimeout-"); resp.flushBuffer(); if (completeOnTimeout){ - if (dispatchUrl == null) { - event.getAsyncContext().complete(); - } else { - event.getAsyncContext().dispatch(dispatchUrl); - } + event.getAsyncContext().complete(); + } + if (dispatchUrl != null) { + event.getAsyncContext().dispatch(dispatchUrl); } } diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 9f7a79c1d..02cb8f72b 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -167,6 +167,11 @@ asynchronous request processing and the socket is immediately closed. (markt) + + Ensure that if asyncDispatch() is called during an onTimeout event and + the target Servlet does not call startAsync() or complete() that Tomcat + calls complete() once the target Servlet exits. (markt) +