-
Bug
-
Resolution: Fixed
-
P4
-
8, 11, 17, 20, 21
-
b26
-
generic
-
generic
-
Verified
A DESCRIPTION OF THE PROBLEM :
When a task within a CompletableFuture encounters an exception and throws a Throwable or Exception object with a faulty 'toString' method, which itself throws another Exception, a cascading failure occurs that causes the CompletableFuture to enter a state where it never completes.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run following code:
public static void main(String[] args) {
CompletableFuture.supplyAsync(() -> {throw new RuntimeException() { @Override public String getMessage() {throw new IllegalArgumentException("getMessage");}};}).join();
}
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
An error is thrown by the 'CompletableFuture.join()' call, preventing this code from hanging forever.
ACTUAL -
The 'CompletableFuture.join()' call never returns or throws an error.
---------- BEGIN SOURCE ----------
public class Test {
public static void main(String[] args) {
var f0 = CompletableFuture.supplyAsync(() -> {
throw new RuntimeException() {
@Override public String getMessage() {
throw new IllegalArgumentException("getMessage");
}
};
});
var f1 = CompletableFuture.supplyAsync(() -> {
throw new RuntimeException() {
@Override public String toString() {
throw new IllegalStateException("toString");
}
};
});
// Never completes
CompletableFuture.anyOf(f0, f1).join();
}
}
---------- END SOURCE ----------
FREQUENCY : always
When a task within a CompletableFuture encounters an exception and throws a Throwable or Exception object with a faulty 'toString' method, which itself throws another Exception, a cascading failure occurs that causes the CompletableFuture to enter a state where it never completes.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run following code:
public static void main(String[] args) {
CompletableFuture.supplyAsync(() -> {throw new RuntimeException() { @Override public String getMessage() {throw new IllegalArgumentException("getMessage");}};}).join();
}
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
An error is thrown by the 'CompletableFuture.join()' call, preventing this code from hanging forever.
ACTUAL -
The 'CompletableFuture.join()' call never returns or throws an error.
---------- BEGIN SOURCE ----------
public class Test {
public static void main(String[] args) {
var f0 = CompletableFuture.supplyAsync(() -> {
throw new RuntimeException() {
@Override public String getMessage() {
throw new IllegalArgumentException("getMessage");
}
};
});
var f1 = CompletableFuture.supplyAsync(() -> {
throw new RuntimeException() {
@Override public String toString() {
throw new IllegalStateException("toString");
}
};
});
// Never completes
CompletableFuture.anyOf(f0, f1).join();
}
}
---------- END SOURCE ----------
FREQUENCY : always