You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2026/10/20 19:04:41 UTC
(tomcat) 05/05: Fix intermittent test failures
This is an automated email from the ASF dual-hosted git repository.
markt-asf pushed a commit to branch 11.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 13f0469f14040a90430c7e302039b260f71e5747
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Tue Oct 20 18:50:44 2026 +0100
Fix intermittent test failures
Co-authored by: Claude / Sonnet 5.5
---
.../apache/tomcat/util/threads/TestTaskQueue.java | 37 ++++++++++++++++------
1 file changed, 28 insertions(+), 9 deletions(-)
diff --git a/test/org/apache/tomcat/util/threads/TestTaskQueue.java b/test/org/apache/tomcat/util/threads/TestTaskQueue.java
index 5c39ddf0dc..96b827431c 100644
--- a/test/org/apache/tomcat/util/threads/TestTaskQueue.java
+++ b/test/org/apache/tomcat/util/threads/TestTaskQueue.java
@@ -30,7 +30,6 @@ public class TestTaskQueue {
private static final long serialVersionUID = 1L;
private final AtomicInteger pollCount = new AtomicInteger();
-
@Override
public Runnable poll(long timeout, TimeUnit unit) throws InterruptedException {
pollCount.incrementAndGet();
@@ -61,15 +60,38 @@ public class TestTaskQueue {
CountDownLatch executed = new CountDownLatch(4);
executor.execute(executed::countDown);
executor.execute(executed::countDown);
- // Wait for both workers to be created and to enter take()
- Thread.sleep(200);
+ // Wait for both tasks to complete and for the workers to finish with them. A worker that is still
+ // running a task when the threads are marked as due to be stopped retires itself without waiting.
+ long deadline = System.nanoTime() + TimeUnit.SECONDS.toNanos(5);
+ while ((executed.getCount() != 2 || executor.getActiveCount() != 0) && System.nanoTime() < deadline) {
+ Thread.sleep(10);
+ }
+ Assert.assertEquals(2, executed.getCount());
+ Assert.assertEquals(0, executor.getActiveCount());
+ // Threads are only due to be stopped if they were created strictly before the context stopped (compared
+ // in milliseconds) so make sure the clock has moved on from the creation of the workers
+ long created = System.currentTimeMillis();
+ while (System.currentTimeMillis() <= created) {
+ Thread.sleep(1);
+ }
- // Mark the (older) worker threads as due to be stopped
+ // Mark the (older) worker threads as due to be stopped. This interrupts the idle workers which then
+ // re-enter take() which, since the threads are due to be stopped, switches to poll() with a bounded
+ // timeout.
executor.contextStopping();
+
+ // Both workers must have entered the renewal wait. Do this before submitting more tasks. If a task is
+ // queued while the interrupt is still being delivered, the worker may return the task from take() rather
+ // than being interrupted and the renewal wait would not be entered.
+ deadline = System.nanoTime() + TimeUnit.SECONDS.toNanos(5);
+ while (queue.pollCount.get() < 2 && System.nanoTime() < deadline) {
+ Thread.sleep(10);
+ }
+ Assert.assertTrue("Renewal wait was not exercised", queue.pollCount.get() >= 2);
+
+ // The workers complete these tasks and then re-enter take()
executor.execute(executed::countDown);
executor.execute(executed::countDown);
- // The workers complete these tasks and then re-enter take() which, since the threads are due to be
- // stopped, switches to poll() with a bounded timeout
Assert.assertTrue(executed.await(5, TimeUnit.SECONDS));
int pollsAfterTask = queue.pollCount.get();
@@ -79,9 +101,6 @@ public class TestTaskQueue {
// Without the bounded timeout this is orders of magnitude larger (millions in this window)
Assert.assertTrue("Unexpected poll count while idle: " + spinIterations, spinIterations < 100);
- // Both workers must have entered the renewal wait at least once
- Assert.assertTrue("Renewal wait was not exercised", queue.pollCount.get() >= 2);
-
// The workers must still be able to process tasks
CountDownLatch processed = new CountDownLatch(1);
executor.execute(processed::countDown);
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org