Skip to content

Commit 7a7f34f

Browse files
committed
Defensive access to volatile ScheduledFuture field
Includes defensive test arrangement for isInThePast() with at least 1 ms having passed. See gh-24560
1 parent 099d016 commit 7a7f34f

File tree

2 files changed

+18
-3
lines changed

2 files changed

+18
-3
lines changed

spring-context/src/main/java/org/springframework/scheduling/config/ScheduledTask.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,9 @@ public void cancel(boolean mayInterruptIfRunning) {
8686
*/
8787
@Nullable
8888
public Instant nextExecution() {
89-
if (this.future != null && !this.future.isCancelled()) {
90-
long delay = this.future.getDelay(TimeUnit.MILLISECONDS);
89+
ScheduledFuture<?> future = this.future;
90+
if (future != null && !future.isCancelled()) {
91+
long delay = future.getDelay(TimeUnit.MILLISECONDS);
9192
if (delay > 0) {
9293
return Instant.now().plusMillis(delay);
9394
}

spring-context/src/test/java/org/springframework/scheduling/config/TaskTests.java

+15-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@
2424

2525
/**
2626
* Tests for {@link Task}.
27+
*
2728
* @author Brian Clozel
29+
* @since 6.2
2830
*/
2931
class TaskTests {
3032

@@ -77,20 +79,32 @@ static class TestRunnable implements Runnable {
7779

7880
@Override
7981
public void run() {
82+
try {
83+
Thread.sleep(1);
84+
}
85+
catch (InterruptedException ex) {
86+
throw new RuntimeException(ex);
87+
}
8088
this.hasRun = true;
8189
}
8290
}
8391

92+
8493
static class FailingTestRunnable implements Runnable {
8594

8695
boolean hasRun;
8796

8897
@Override
8998
public void run() {
99+
try {
100+
Thread.sleep(1);
101+
}
102+
catch (InterruptedException ex) {
103+
throw new RuntimeException(ex);
104+
}
90105
this.hasRun = true;
91106
throw new IllegalStateException("test exception");
92107
}
93108
}
94109

95-
96110
}

0 commit comments

Comments
 (0)