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

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

commit 572ca3155087f11436a936286ff4de65aa850375
Author: opencode <[email protected]>
AuthorDate: Fri Oct 16 15:31:00 2026 +0200

    Shut down the internal virtual thread executor when the endpoint stops
    
    shutdownExecutor() only shut down the thread pool branch, leaving a
    virtual thread executor accepting tasks submitted through a reference
    captured before the stop. Shut it down as well, so such submissions
    are rejected, as they already are with the thread pool executor.
---
 .../apache/tomcat/util/net/AbstractEndpoint.java   |  6 +++
 .../tomcat/util/net/TestAbstractEndpoint.java      | 44 ++++++++++++++++++++++
 2 files changed, 50 insertions(+)

diff --git a/java/org/apache/tomcat/util/net/AbstractEndpoint.java 
b/java/org/apache/tomcat/util/net/AbstractEndpoint.java
index 6d030f69f3..bb354c2611 100644
--- a/java/org/apache/tomcat/util/net/AbstractEndpoint.java
+++ b/java/org/apache/tomcat/util/net/AbstractEndpoint.java
@@ -1793,6 +1793,12 @@ public abstract class AbstractEndpoint<S, U> {
                 }
                 TaskQueue queue = (TaskQueue) tpe.getQueue();
                 queue.setParent(null);
+            } else if (executor instanceof VirtualThreadExecutor 
virtualThreadExecutor) {
+                // The virtual thread executor accepts new tasks until it is 
shut
+                // down. Shut it down, so tasks submitted via a reference 
captured
+                // before this point are rejected, as they are with the thread
+                // pool executor.
+                virtualThreadExecutor.shutdownNow();
             }
         }
     }
diff --git a/test/org/apache/tomcat/util/net/TestAbstractEndpoint.java 
b/test/org/apache/tomcat/util/net/TestAbstractEndpoint.java
index 055cab7512..4b06e254c9 100644
--- a/test/org/apache/tomcat/util/net/TestAbstractEndpoint.java
+++ b/test/org/apache/tomcat/util/net/TestAbstractEndpoint.java
@@ -16,12 +16,17 @@
  */
 package org.apache.tomcat.util.net;
 
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import java.util.concurrent.RejectedExecutionException;
 import java.util.concurrent.ScheduledExecutorService;
 
 import org.junit.Assert;
 import org.junit.Test;
 
+import org.apache.tomcat.util.threads.VirtualThreadExecutor;
+
 public class TestAbstractEndpoint {
 
     @Test
@@ -65,4 +70,43 @@ public class TestAbstractEndpoint {
             executor.shutdown();
         }
     }
+
+    /*
+     * The virtual thread executor accepts tasks until it is shut down. A 
reference captured before the endpoint
+     * stopped must be rejected, as it is when the executor is a thread pool.
+     */
+    @Test
+    public void testCreatedVirtualThreadExecutorIsShutDownOnStop() throws 
Exception {
+        NioEndpoint endpoint = new NioEndpoint();
+        endpoint.setUseVirtualThreads(true);
+        endpoint.createExecutor();
+        Executor executor = endpoint.getExecutor();
+        Assert.assertTrue(executor instanceof VirtualThreadExecutor);
+
+        endpoint.shutdownExecutor();
+
+        Assert.assertTrue(((ExecutorService) executor).isShutdown());
+        try {
+            executor.execute(() -> {
+            });
+            Assert.fail("Expected RejectedExecutionException");
+        } catch (RejectedExecutionException e) {
+            // Expected.
+        }
+    }
+
+    @Test
+    public void testExternalVirtualThreadExecutorIsNotShutDownOnStop() throws 
Exception {
+        NioEndpoint endpoint = new NioEndpoint();
+        VirtualThreadExecutor executor = new 
VirtualThreadExecutor("test-external-");
+        endpoint.setExecutor(executor);
+        try {
+            endpoint.shutdownExecutor();
+
+            // Externally provided executors are owned by the caller
+            Assert.assertFalse(executor.isShutdown());
+        } finally {
+            executor.shutdownNow();
+        }
+    }
 }


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

Reply via email to