Skip to content

Commit f6a53ee

Browse files
committed
Ensure AsyncTask#isScheduled remain false after close (#45687)
If a scheduled task of an AbstractAsyncTask starts after it was closed, then isScheduledOrRunning can remain true forever although no task is running or scheduled. Closes #45576
1 parent 05ae8f2 commit f6a53ee

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

server/src/main/java/org/elasticsearch/common/util/concurrent/AbstractAsyncTask.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,9 @@ public boolean isClosed() {
134134
@Override
135135
public final void run() {
136136
synchronized (this) {
137+
if (isClosed()) {
138+
return;
139+
}
137140
cancellable = null;
138141
isScheduledOrRunning = autoReschedule;
139142
}

server/src/test/java/org/elasticsearch/common/util/concurrent/AbstractAsyncTaskTests.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,23 @@
1818
*/
1919
package org.elasticsearch.common.util.concurrent;
2020

21+
import org.elasticsearch.common.Randomness;
2122
import org.elasticsearch.common.unit.TimeValue;
23+
import org.elasticsearch.core.internal.io.IOUtils;
2224
import org.elasticsearch.test.ESTestCase;
2325
import org.elasticsearch.threadpool.TestThreadPool;
2426
import org.elasticsearch.threadpool.ThreadPool;
2527
import org.junit.AfterClass;
2628
import org.junit.BeforeClass;
2729

30+
import java.util.ArrayList;
31+
import java.util.List;
2832
import java.util.concurrent.CountDownLatch;
2933
import java.util.concurrent.CyclicBarrier;
3034
import java.util.concurrent.TimeUnit;
3135
import java.util.concurrent.TimeoutException;
3236
import java.util.concurrent.atomic.AtomicInteger;
37+
import java.util.concurrent.atomic.AtomicLong;
3338

3439
public class AbstractAsyncTaskTests extends ESTestCase {
3540

@@ -203,4 +208,31 @@ protected void runInternal() {
203208
assertFalse(task.isScheduled());
204209
assertTrue(task.isClosed());
205210
}
211+
212+
public void testIsScheduledRemainFalseAfterClose() throws Exception {
213+
int numTasks = between(10, 50);
214+
List<AbstractAsyncTask> tasks = new ArrayList<>(numTasks);
215+
AtomicLong counter = new AtomicLong();
216+
for (int i = 0; i < numTasks; i++) {
217+
AbstractAsyncTask task = new AbstractAsyncTask(logger, threadPool, TimeValue.timeValueMillis(randomIntBetween(1, 2)), true) {
218+
@Override
219+
protected boolean mustReschedule() {
220+
return counter.get() <= 1000;
221+
}
222+
@Override
223+
protected void runInternal() {
224+
counter.incrementAndGet();
225+
}
226+
};
227+
task.rescheduleIfNecessary();
228+
tasks.add(task);
229+
}
230+
Randomness.shuffle(tasks);
231+
IOUtils.close(tasks);
232+
Randomness.shuffle(tasks);
233+
for (AbstractAsyncTask task : tasks) {
234+
assertTrue(task.isClosed());
235+
assertFalse(task.isScheduled());
236+
}
237+
}
206238
}

0 commit comments

Comments
 (0)