From 6c77bf024abd07416e94c624076500140418bcbe Mon Sep 17 00:00:00 2001 From: markt Date: Tue, 28 Jun 2011 17:24:45 +0000 Subject: [PATCH] Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=50353 Rather than the eventual NPE, throw an ISE if an application attempts to access an AsyncContext after the request processing has ended. git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@1140738 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/catalina/core/AsyncContextImpl.java | 35 +++++++++++++++++++--- .../apache/catalina/core/LocalStrings.properties | 1 + 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/java/org/apache/catalina/core/AsyncContextImpl.java b/java/org/apache/catalina/core/AsyncContextImpl.java index b36ce22e1..2e6d6e0ca 100644 --- a/java/org/apache/catalina/core/AsyncContextImpl.java +++ b/java/org/apache/catalina/core/AsyncContextImpl.java @@ -48,6 +48,7 @@ import org.apache.coyote.RequestInfo; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.tomcat.InstanceManager; +import org.apache.tomcat.util.res.StringManager; /** * * @author fhanik @@ -57,6 +58,9 @@ public class AsyncContextImpl implements AsyncContext, AsyncContextCallback { private static final Log log = LogFactory.getLog(AsyncContextImpl.class); + protected static final StringManager sm = + StringManager.getManager(Constants.Package); + private ServletRequest servletRequest = null; private ServletResponse servletResponse = null; private List listeners = new ArrayList(); @@ -80,6 +84,7 @@ public class AsyncContextImpl implements AsyncContext, AsyncContextCallback { if (log.isDebugEnabled()) { logDebug("complete "); } + check(); request.getCoyoteRequest().action(ActionCode.COMMIT, null); request.getCoyoteRequest().action(ActionCode.ASYNC_COMPLETE, null); } @@ -126,6 +131,7 @@ public class AsyncContextImpl implements AsyncContext, AsyncContextCallback { @Override public void dispatch() { + check(); HttpServletRequest sr = (HttpServletRequest)getRequest(); String path = sr.getRequestURI(); String cpath = sr.getContextPath(); @@ -135,6 +141,7 @@ public class AsyncContextImpl implements AsyncContext, AsyncContextCallback { @Override public void dispatch(String path) { + check(); dispatch(request.getServletContext(),path); } @@ -143,6 +150,7 @@ public class AsyncContextImpl implements AsyncContext, AsyncContextCallback { if (log.isDebugEnabled()) { logDebug("dispatch "); } + check(); if (request.getAttribute(ASYNC_REQUEST_URI)==null) { request.setAttribute(ASYNC_REQUEST_URI, request.getRequestURI()+"?"+request.getQueryString()); request.setAttribute(ASYNC_CONTEXT_PATH, request.getContextPath()); @@ -178,11 +186,13 @@ public class AsyncContextImpl implements AsyncContext, AsyncContextCallback { @Override public ServletRequest getRequest() { + check(); return servletRequest; } @Override public ServletResponse getResponse() { + check(); return servletResponse; } @@ -191,13 +201,14 @@ public class AsyncContextImpl implements AsyncContext, AsyncContextCallback { if (log.isDebugEnabled()) { logDebug("start "); } - + check(); Runnable wrapper = new RunnableWrapper(run, context); this.request.getCoyoteRequest().action(ActionCode.ASYNC_RUN, wrapper); } @Override public void addListener(AsyncListener listener) { + check(); AsyncListenerWrapper wrapper = new AsyncListenerWrapper(); wrapper.setListener(listener); listeners.add(wrapper); @@ -206,6 +217,7 @@ public class AsyncContextImpl implements AsyncContext, AsyncContextCallback { @Override public void addListener(AsyncListener listener, ServletRequest servletRequest, ServletResponse servletResponse) { + check(); AsyncListenerWrapper wrapper = new AsyncListenerWrapper(); wrapper.setListener(listener); listeners.add(wrapper); @@ -215,6 +227,7 @@ public class AsyncContextImpl implements AsyncContext, AsyncContextCallback { @Override public T createListener(Class clazz) throws ServletException { + check(); T listener = null; try { listener = (T) getInstanceManager().newInstance(clazz.getName(), @@ -242,12 +255,16 @@ public class AsyncContextImpl implements AsyncContext, AsyncContextCallback { if (log.isDebugEnabled()) { logDebug("recycle "); } + context = null; + dispatch = null; + event = null; + hasOriginalRequestAndResponse = true; + instanceManager = null; + listeners.clear(); + request = null; servletRequest = null; servletResponse = null; - hasOriginalRequestAndResponse = true; - context = null; timeout = -1; - event = null; } public boolean isStarted() { @@ -285,6 +302,7 @@ public class AsyncContextImpl implements AsyncContext, AsyncContextCallback { @Override public boolean hasOriginalRequestAndResponse() { + check(); return hasOriginalRequestAndResponse; } @@ -309,12 +327,14 @@ public class AsyncContextImpl implements AsyncContext, AsyncContextCallback { @Override public long getTimeout() { + check(); return timeout; } @Override public void setTimeout(long timeout) { + check(); this.timeout = timeout; request.getCoyoteRequest().action(ActionCode.ASYNC_SETTIMEOUT, Long.valueOf(timeout)); @@ -407,6 +427,13 @@ public class AsyncContextImpl implements AsyncContext, AsyncContextCallback { return instanceManager; } + private void check() { + if (request == null) { + // AsyncContext has been recycled and should not be being used + throw new IllegalStateException(sm.getString( + "asyncContextImpl.requestEnded")); + } + } private static class DebugException extends Exception { private static final long serialVersionUID = 1L; } diff --git a/java/org/apache/catalina/core/LocalStrings.properties b/java/org/apache/catalina/core/LocalStrings.properties index 39e8cabae..f49e83198 100644 --- a/java/org/apache/catalina/core/LocalStrings.properties +++ b/java/org/apache/catalina/core/LocalStrings.properties @@ -59,6 +59,7 @@ aprListener.aprDestroy=Failed shutdown of APR based Apache Tomcat Native library aprListener.sslInit=Failed to initialize the SSLEngine. aprListener.tcnValid=Loaded APR based Apache Tomcat Native library {0}. aprListener.flags=APR capabilities: IPv6 [{0}], sendfile [{1}], accept filters [{2}], random [{3}]. +asyncContextImpl.requestEnded=The request associated with the AsyncContext has already completed processing. containerBase.alreadyStarted=Container {0} has already been started containerBase.notConfigured=No basic Valve has been configured containerBase.notStarted=Container {0} has not been started -- 2.11.0