-
Bug
-
Resolution: Fixed
-
P3
-
11, 15
-
b29
-
Verified
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8258367 | 17 | Martin Buchholz | P3 | Resolved | Fixed | b02 |
JDK-8308359 | 11.0.21-oracle | Ryan Wallace | P3 | Resolved | Fixed | b01 |
JDK-8310865 | 11.0.21 | Goetz Lindenmaier | P3 | Resolved | Fixed | b01 |
`CompletableFuture.get` may swallow `InterruptedException` if waiting thread is interrupted and waiting future completes immediately after.
This issues exist in openjdk 9 and above, but not openjdk 8.
I have created a github repository with analysis and testing code. See https://github.com/kezhuw/openjdk-completablefuture-interruptedexception if it helps.
REGRESSION : Last worked in version 8u261
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Calls `CompletableFuture.get` on note completed future future-a in thread-a.
2. Interrupts thread-a and completes future-a.
3. If future-a completes normally, the interrupt status may be swallowed in openjdk 9 and above.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
If `CompletableFuture.get` completes normally, interrupt status should be keep.
ACTUAL -
After `CompletableFuture.get` completes normally, interrupt status may be swallowed.
---------- BEGIN SOURCE ----------
import java.io.PrintStream;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadLocalRandom;
public class CompletableFutureGet0 {
private static final PrintStream stdout = System.out;
private static final PrintStream stderr = System.err;
private static final String futureMethod = "get";
private static final FutureWaiter futureWaiter = CompletableFuture::get;
private static final int maxRuns = 1000;
@FunctionalInterface
interface FutureWaiter {
void wait(CompletableFuture<Void> future) throws InterruptedException, ExecutionException;
}
public static void main(String[] args) throws Exception {
for (int i = 1; i <= maxRuns; i++) {
long sleepMills = ThreadLocalRandom.current().nextLong(10);
final String sleepString = sleepMills == 0 ? "--------" : String.format("sleep(%d)", sleepMills);
final String prefix = String.format("%4d/%d interrupt-%s-complete", i, maxRuns, sleepString);
CompletableFuture<Void> future = new CompletableFuture<>();
CountDownLatch waitingFutureLatch = new CountDownLatch(1);
CountDownLatch futureGotLatch = new CountDownLatch(1);
Thread futureGetThread = new Thread(() -> {
try {
waitingFutureLatch.countDown();
futureWaiter.wait(future);
// XXX: Test whether interrupt status was lost.
if (Thread.currentThread().isInterrupted()) {
stdout.format("%s: future.%s completes, Thread.isInterrupted returns true\n", prefix, futureMethod);
} else {
stderr.format("%s: future.%s completes, Thread.isInterrupted returns false\n", prefix, futureMethod);
System.exit(1);
}
} catch (InterruptedException ex) {
stdout.format("%s: future.%s is interrupted.\n", prefix, futureMethod);
try {
futureWaiter.wait(future);
} catch (Exception ex1) {
stderr.println("Got unexpected exception");
ex.printStackTrace();
System.exit(128);
}
} catch (ExecutionException ex) {
stderr.println("Got unexpected execution exception");
ex.printStackTrace();
System.exit(128);
}
futureGotLatch.countDown();
}, String.format("future-get-thread-%d", i));
futureGetThread.setDaemon(true);
futureGetThread.start();
waitingFutureLatch.await();
Thread.sleep(1);
try {
futureGetThread.interrupt();
if (sleepMills > 0) {
Thread.sleep(sleepMills);
}
future.complete(null);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
futureGotLatch.await();
}
}
}
---------- END SOURCE ----------
FREQUENCY : often
- backported by
-
JDK-8258367 CompletableFuture.get may swallow InterruptedException
- Resolved
-
JDK-8308359 CompletableFuture.get may swallow InterruptedException
- Resolved
-
JDK-8310865 CompletableFuture.get may swallow InterruptedException
- Resolved
- relates to
-
SKARA-845 pr integrate: "timed out waiting for response to /integrate command"
- Closed
-
JDK-8259796 timed CompletableFuture.get may swallow InterruptedException
- Closed
- links to
-
Commit openjdk/jdk11u-dev/5506ecf3
-
Commit openjdk/jdk16/43dc3f79
-
Review openjdk/jdk11u-dev/1961
-
Review openjdk/jdk11u-dev/1964
-
Review openjdk/jdk16/17
-
Review openjdk/jdk/1651