From 9041527f94e3d5456f3f2439c689bf891a805c2f Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Wed, 21 Jun 2023 11:18:43 +0200 Subject: [PATCH] Fix #9476 IteratingCallback multiple onCompleteFailure calls (#9940) Change state to FAILED from PENDING state --- .../eclipse/jetty/util/IteratingCallback.java | 1 + .../jetty/util/IteratingCallbackTest.java | 41 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/IteratingCallback.java b/jetty-util/src/main/java/org/eclipse/jetty/util/IteratingCallback.java index 4ba8bc67753..634dc52a033 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/IteratingCallback.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/IteratingCallback.java @@ -400,6 +400,7 @@ public abstract class IteratingCallback implements Callback break; case PENDING: { + _state = State.FAILED; failure = true; break; } diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/IteratingCallbackTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/IteratingCallbackTest.java index 668d9bf1f9d..d588ab518bc 100644 --- a/jetty-util/src/test/java/org/eclipse/jetty/util/IteratingCallbackTest.java +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/IteratingCallbackTest.java @@ -15,6 +15,7 @@ package org.eclipse.jetty.util; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler; import org.eclipse.jetty.util.thread.Scheduler; @@ -322,4 +323,44 @@ public class IteratingCallbackTest return isSucceeded(); } } + + @Test + public void testMultipleFailures() throws Exception + { + AtomicInteger process = new AtomicInteger(); + AtomicInteger failure = new AtomicInteger(); + IteratingCallback icb = new IteratingCallback() + { + @Override + protected Action process() throws Throwable + { + process.incrementAndGet(); + return Action.SCHEDULED; + } + + @Override + protected void onCompleteFailure(Throwable cause) + { + super.onCompleteFailure(cause); + failure.incrementAndGet(); + } + }; + + icb.iterate(); + assertEquals(1, process.get()); + assertEquals(0, failure.get()); + + icb.failed(new Throwable("test1")); + + assertEquals(1, process.get()); + assertEquals(1, failure.get()); + + icb.succeeded(); + assertEquals(1, process.get()); + assertEquals(1, failure.get()); + + icb.failed(new Throwable("test2")); + assertEquals(1, process.get()); + assertEquals(1, failure.get()); + } }