Author: markt
Date: Wed Jan 23 16:33:47 2019
New Revision: 1851947

URL: http://svn.apache.org/viewvc?rev=1851947&view=rev
Log:
Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63003
Extend the unloadDelay attribute on a Context to include in-flight asynchronous 
requests.

Modified:
    tomcat/trunk/java/org/apache/catalina/Context.java
    tomcat/trunk/java/org/apache/catalina/core/AsyncContextImpl.java
    tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties
    tomcat/trunk/java/org/apache/catalina/core/StandardContext.java
    tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java
    tomcat/trunk/java/org/apache/coyote/AbstractProcessor.java
    tomcat/trunk/java/org/apache/coyote/AsyncContextCallback.java
    tomcat/trunk/java/org/apache/coyote/AsyncStateMachine.java
    tomcat/trunk/test/org/apache/tomcat/unittest/TesterContext.java
    tomcat/trunk/webapps/docs/changelog.xml

Modified: tomcat/trunk/java/org/apache/catalina/Context.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/Context.java?rev=1851947&r1=1851946&r2=1851947&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/Context.java (original)
+++ tomcat/trunk/java/org/apache/catalina/Context.java Wed Jan 23 16:33:47 2019
@@ -1865,4 +1865,10 @@ public interface Context extends Contain
      *         otherwise <code>false</code>
      */
     public boolean getAllowMultipleLeadingForwardSlashInPath();
+
+
+    public void incrementInProgressAsyncCount();
+
+
+    public void decrementInProgressAsyncCount();
 }

Modified: tomcat/trunk/java/org/apache/catalina/core/AsyncContextImpl.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/AsyncContextImpl.java?rev=1851947&r1=1851946&r2=1851947&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/AsyncContextImpl.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/AsyncContextImpl.java Wed Jan 23 
16:33:47 2019
@@ -111,6 +111,7 @@ public class AsyncContextImpl implements
         } finally {
             context.fireRequestDestroyEvent(request.getRequest());
             clearServletRequestResponse();
+            this.context.decrementInProgressAsyncCount();
             context.unbind(Globals.IS_SECURITY_ENABLED, oldCL);
         }
     }
@@ -205,6 +206,7 @@ public class AsyncContextImpl implements
                     request, applicationDispatcher, servletRequest, 
servletResponse);
             this.request.getCoyoteRequest().action(ActionCode.ASYNC_DISPATCH, 
null);
             clearServletRequestResponse();
+            this.context.decrementInProgressAsyncCount();
         }
     }
 
@@ -311,6 +313,7 @@ public class AsyncContextImpl implements
                     ActionCode.ASYNC_START, this);
 
             this.context = context;
+            context.incrementInProgressAsyncCount();
             this.servletRequest = request;
             this.servletResponse = response;
             this.hasOriginalRequestAndResponse = originalRequestResponse;
@@ -377,6 +380,17 @@ public class AsyncContextImpl implements
     }
 
 
+
+    @Override
+    public boolean isAvailable() {
+        Context context = this.context;
+        if (context == null) {
+            return false;
+        }
+        return context.getState().isAvailable();
+    }
+
+
     public void setErrorState(Throwable t, boolean fireOnError) {
         if (t!=null) request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, 
t);
         request.getCoyoteRequest().action(ActionCode.ASYNC_ERROR, null);

Modified: tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties?rev=1851947&r1=1851946&r2=1851947&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties [UTF-8] 
(original)
+++ tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties [UTF-8] 
Wed Jan 23 16:33:47 2019
@@ -222,6 +222,7 @@ standardContext.setManager.start=Error s
 standardContext.setManager.stop=Error stopping old manager
 standardContext.startFailed=Context [{0}] startup failed due to previous errors
 standardContext.startingContext=Exception starting Context with name [{0}]
+standardContext.stop.asyncWaitInterrupted=Interrupt received while waiting 
unloadDelay milliseconds for in-flight asynchronous requests to complete. 
Context stop will continue without further delay.
 standardContext.stoppingContext=Exception stopping Context with name [{0}]
 standardContext.suspiciousUrl=Suspicious URL pattern: [{0}] in context [{1}], 
see sections 12.1 and 12.2 of the Servlet specification
 standardContext.threadBindingListenerError=An error occurred in the thread 
binding listener configured for Context [{0}]

Modified: tomcat/trunk/java/org/apache/catalina/core/StandardContext.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/StandardContext.java?rev=1851947&r1=1851946&r2=1851947&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/StandardContext.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/StandardContext.java Wed Jan 23 
16:33:47 2019
@@ -820,10 +820,24 @@ public class StandardContext extends Con
 
     private boolean allowMultipleLeadingForwardSlashInPath = false;
 
+    private final AtomicLong inProgressAsyncCount = new AtomicLong(0);
+
 
     // ----------------------------------------------------- Context Properties
 
     @Override
+    public void incrementInProgressAsyncCount() {
+        inProgressAsyncCount.incrementAndGet();
+    }
+
+
+    @Override
+    public void decrementInProgressAsyncCount() {
+        inProgressAsyncCount.decrementAndGet();
+    }
+
+
+    @Override
     public void setAllowMultipleLeadingForwardSlashInPath(
             boolean allowMultipleLeadingForwardSlashInPath) {
         this.allowMultipleLeadingForwardSlashInPath = 
allowMultipleLeadingForwardSlashInPath;
@@ -5316,6 +5330,22 @@ public class StandardContext extends Con
             broadcaster.sendNotification(notification);
         }
 
+        // Context has been removed from Mapper at this point (so no new
+        // requests will be mapped) but is still available.
+
+        // Give the in progress async requests a chance to complete
+        long limit = System.currentTimeMillis() + unloadDelay;
+        while (inProgressAsyncCount.get() > 0 && System.currentTimeMillis() < 
limit) {
+            try {
+                Thread.sleep(50);
+            } catch (InterruptedException e) {
+                
log.info(sm.getString("standardContext.stop.asyncWaitInterrupted"), e);
+                break;
+            }
+        }
+
+        // Once the state is set to STOPPING, the Context will report itself as
+        // not available and any in progress async requests will timeout
         setState(LifecycleState.STOPPING);
 
         // Binding thread

Modified: tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java?rev=1851947&r1=1851946&r2=1851947&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java (original)
+++ tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java Wed Jan 23 
16:33:47 2019
@@ -809,4 +809,9 @@ public class FailedContext extends Lifec
     }
     @Override
     public boolean getAllowMultipleLeadingForwardSlashInPath() { return false; 
}
+
+    @Override
+    public void incrementInProgressAsyncCount() { /* NO-OP */ }
+    @Override
+    public void decrementInProgressAsyncCount() { /* NO-OP */ }
 }
\ No newline at end of file

Modified: tomcat/trunk/java/org/apache/coyote/AbstractProcessor.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/AbstractProcessor.java?rev=1851947&r1=1851946&r2=1851947&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/AbstractProcessor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/AbstractProcessor.java Wed Jan 23 
16:33:47 2019
@@ -639,6 +639,10 @@ public abstract class AbstractProcessor
                 if ((now - asyncStart) > asyncTimeout) {
                     doTimeoutAsync();
                 }
+            } else if (!asyncStateMachine.isAvailable()) {
+                // Timeout the async process if the associated web application
+                // is no longer running.
+                doTimeoutAsync();
             }
         }
     }

Modified: tomcat/trunk/java/org/apache/coyote/AsyncContextCallback.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/AsyncContextCallback.java?rev=1851947&r1=1851946&r2=1851947&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/AsyncContextCallback.java (original)
+++ tomcat/trunk/java/org/apache/coyote/AsyncContextCallback.java Wed Jan 23 
16:33:47 2019
@@ -17,12 +17,20 @@
 package org.apache.coyote;
 
 /**
- * Provides a mechanism for the Coyote connectors to signal to a
- * {@link javax.servlet.AsyncContext} implementation that an action, such as
- * firing event listeners needs to be taken. It is implemented in this manner
- * so that the org.apache.coyote package does not have a dependency on the
+ * Provides a mechanism for the Coyote connectors to communicate with the
+ * {@link javax.servlet.AsyncContext}. It is implemented in this manner so that
+ * the org.apache.coyote package does not have a dependency on the
  * org.apache.catalina package.
  */
 public interface AsyncContextCallback {
     public void fireOnComplete();
+
+    /**
+     * Reports if the web application associated with this async request is
+     * available.
+     *
+     * @return {@code true} if the associated web application is available,
+     *         otherwise {@code false}
+     */
+    public boolean isAvailable();
 }

Modified: tomcat/trunk/java/org/apache/coyote/AsyncStateMachine.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/AsyncStateMachine.java?rev=1851947&r1=1851946&r2=1851947&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/AsyncStateMachine.java [UTF-8] 
(original)
+++ tomcat/trunk/java/org/apache/coyote/AsyncStateMachine.java [UTF-8] Wed Jan 
23 16:33:47 2019
@@ -483,6 +483,16 @@ class AsyncStateMachine {
     }
 
 
+    synchronized boolean isAvailable() {
+        if (asyncCtxt == null) {
+            // Async processing has probably been completed in another thread.
+            // Trigger a timeout to make sure the Processor is cleaned up.
+            return false;
+        }
+        return asyncCtxt.isAvailable();
+    }
+
+
     synchronized void recycle() {
         // Use lastAsyncStart to determine if this instance has been used since
         // it was last recycled. If it hasn't there is no need to recycle again

Modified: tomcat/trunk/test/org/apache/tomcat/unittest/TesterContext.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/unittest/TesterContext.java?rev=1851947&r1=1851946&r2=1851947&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/tomcat/unittest/TesterContext.java (original)
+++ tomcat/trunk/test/org/apache/tomcat/unittest/TesterContext.java Wed Jan 23 
16:33:47 2019
@@ -1274,4 +1274,9 @@ public class TesterContext implements Co
     }
     @Override
     public boolean getAllowMultipleLeadingForwardSlashInPath() { return false; 
}
+
+    @Override
+    public void incrementInProgressAsyncCount() { /* NO-OP */ }
+    @Override
+    public void decrementInProgressAsyncCount() { /* NO-OP */ }
 }

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1851947&r1=1851946&r2=1851947&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Wed Jan 23 16:33:47 2019
@@ -113,6 +113,10 @@
         <code>trimCredentials</code> on the <code>BasicAuthenticator</code>.
         (markt)
       </add>
+      <fix>
+        <bug>63003</bug>: Extend the <code>unloadDelay</code> attribute on a
+        <code>Context</code> to include in-flight asynchronous requests. 
(markt)
+      </fix>
       <add>
         <bug>63026</bug>: Add a new attribute, <code>forceDnHexEscape</code>, 
to
         the <code>JNDIRealm</code> that forces escaping in the String



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

Reply via email to