This is an automated email from the ASF dual-hosted git repository.
JingsongLi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git
The following commit(s) were added to refs/heads/master by this push:
new 72caec1dff [api] Fix race condition causing queued tasks to execute
after SequentialBatchIterator close (#9452)
72caec1dff is described below
commit 72caec1dffe66e02fe660545cc7cde535cbbcb11
Author: Juntao Zhang <[email protected]>
AuthorDate: Sat Aug 29 20:55:26 2026 +0800
[api] Fix race condition causing queued tasks to execute after
SequentialBatchIterator close (#9452)
---
.../org/apache/paimon/utils/ThreadPoolUtils.java | 24 +++++++++++++++++-----
1 file changed, 19 insertions(+), 5 deletions(-)
diff --git
a/paimon-api/src/main/java/org/apache/paimon/utils/ThreadPoolUtils.java
b/paimon-api/src/main/java/org/apache/paimon/utils/ThreadPoolUtils.java
index b5c28a19a0..b7151afbbd 100644
--- a/paimon-api/src/main/java/org/apache/paimon/utils/ThreadPoolUtils.java
+++ b/paimon-api/src/main/java/org/apache/paimon/utils/ThreadPoolUtils.java
@@ -229,7 +229,7 @@ public class ThreadPoolUtils {
private Iterator<T> activeResults =
Collections.<T>emptyList().iterator();
private T next;
- private boolean closed;
+ private volatile boolean closed;
private SequentialBatchIterator(
ExecutorService executor,
@@ -243,7 +243,7 @@ public class ThreadPoolUtils {
@Override
public boolean hasNext() {
- if (!closed) {
+ if (!isClosed()) {
advanceIfNeeded();
}
return next != null;
@@ -259,6 +259,10 @@ public class ThreadPoolUtils {
return result;
}
+ private boolean isClosed() {
+ return closed;
+ }
+
private void advanceIfNeeded() {
while (next == null) {
if (activeResults.hasNext()) {
@@ -286,7 +290,7 @@ public class ThreadPoolUtils {
private void submitBatch(List<U> batch) {
ClassLoader classLoader =
Thread.currentThread().getContextClassLoader();
for (U input : batch) {
- BatchTask<T, U> task = new BatchTask<>(processor, input,
classLoader);
+ BatchTask<T, U> task = new BatchTask<>(this, processor, input,
classLoader);
executor.execute(task);
activeTasks.add(task);
}
@@ -343,6 +347,7 @@ public class ThreadPoolUtils {
private static final int CANCELLED = 2;
private static final int FINISHED = 3;
+ private final SequentialBatchIterator<T, U> iterator;
private final Function<U, List<T>> processor;
private final U input;
private final ClassLoader classLoader;
@@ -354,7 +359,12 @@ public class ThreadPoolUtils {
private Throwable failure;
private volatile boolean failureReported;
- private BatchTask(Function<U, List<T>> processor, U input, ClassLoader
classLoader) {
+ private BatchTask(
+ SequentialBatchIterator<T, U> iterator,
+ Function<U, List<T>> processor,
+ U input,
+ ClassLoader classLoader) {
+ this.iterator = iterator;
this.processor = processor;
this.input = input;
this.classLoader = classLoader;
@@ -363,7 +373,7 @@ public class ThreadPoolUtils {
@Override
public void run() {
synchronized (this) {
- if (state == CANCELLED) {
+ if (isCanceled()) {
state = FINISHED;
completion.countDown();
return;
@@ -386,6 +396,10 @@ public class ThreadPoolUtils {
}
}
+ private boolean isCanceled() {
+ return state == CANCELLED || iterator.isClosed();
+ }
+
private synchronized void cancel() {
if (state == CREATED) {
state = CANCELLED;