This is an automated email from the ASF dual-hosted git repository.

rmaucher pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/main by this push:
     new fb35455523 Add API callback to allow avoiding recycling processors
fb35455523 is described below

commit fb35455523418aa4b30e24a720a427fb1485d1fd
Author: remm <[email protected]>
AuthorDate: Wed Nov 11 09:12:07 2026 +0100

    Add API callback to allow avoiding recycling processors
    
    Same reason for HTTP/3 as for HTTP/2 (which is an upgrade protocol, so
    it does it without the API).
---
 java/org/apache/coyote/AbstractProtocol.java | 13 ++++++++++++-
 java/org/apache/coyote/Processor.java        | 13 +++++++++++++
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/java/org/apache/coyote/AbstractProtocol.java 
b/java/org/apache/coyote/AbstractProtocol.java
index 2f450ae9a9..5089e529b1 100644
--- a/java/org/apache/coyote/AbstractProtocol.java
+++ b/java/org/apache/coyote/AbstractProtocol.java
@@ -1676,7 +1676,11 @@ public abstract class AbstractProtocol<S> implements 
ProtocolHandler, MBeanRegis
         }
 
         /**
-         * Pushes a processor to the pool.
+         * Pushes a processor to the pool. A processor that is not reusable is
+         * not added to the pool and is unregistered instead. This may happen,
+         * for example, after an asynchronous timeout or error while an
+         * application thread was blocked in a write. Reusing such a processor
+         * could write stale data to another request.
          *
          * @param processor The processor
          *
@@ -1685,6 +1689,13 @@ public abstract class AbstractProtocol<S> implements 
ProtocolHandler, MBeanRegis
         @SuppressWarnings("sync-override") // Size may exceed cache size a bit
         @Override
         public boolean push(Processor processor) {
+            if (!processor.isReusable()) {
+                // Also make sure any waiting-processor registration is
+                // removed before the processor is unregistered.
+                handler.getProtocol().removeWaitingProcessor(processor);
+                handler.unregister(processor);
+                return false;
+            }
             int cacheSize = handler.getProtocol().getProcessorCache();
             boolean offer = cacheSize == -1 || size.get() < cacheSize;
             // avoid over growing our cache or add after we have stopped
diff --git a/java/org/apache/coyote/Processor.java 
b/java/org/apache/coyote/Processor.java
index e5f82f09e2..d7f816afb4 100644
--- a/java/org/apache/coyote/Processor.java
+++ b/java/org/apache/coyote/Processor.java
@@ -89,6 +89,19 @@ public interface Processor {
      */
     void recycle();
 
+    /**
+     * Whether this processor may be returned to the shared processor pool
+     * after {@link #recycle()}. A processor must not be reused if a
+     * non-container thread may still be using its request, response or
+     * output state (for example after an asynchronous timeout or error
+     * while an application thread was blocked in a write).
+     *
+     * @return {@code true} if the processor may be pooled for reuse
+     */
+    default boolean isReusable() {
+        return true;
+    }
+
     /**
      * Set the SSL information for this HTTP connection.
      *


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to