-
Bug
-
Resolution: Unresolved
-
P4
-
8, 11, 18
-
generic
-
generic
A DESCRIPTION OF THE PROBLEM :
https://stackoverflow.com/q/69034337/3788176
https://www.mycompiler.io/new/java?fork=AY0soH4
Here, a CompleteableFuture is cancelled, and then joined in quick succession. The join results in a CancellationException being thrown, which is expected.
However, the stack trace of the exception thrown is the stack trace captured at the time of the `f.cancel(true);` call, which leads to the erroneous impression that the exception is being _thrown_ on the `f.cancel(true);` call.
In a more realistic production scenario, the `cancel` and `join` calls are probably not going to be as close together as that. This could lead to a total wild goose chase of trying to work out why an exception was being thrown in one place (and potentially make it look, confusingly, as though statements after that exception were still being invoked), whereas in fact execution is being stopped somewhere completely different.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run source code
```
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
// The main method must be in a class named "Main".
class Main {
public static void main(String[] args) {
System.out.println(System.getProperty("java.version"));
CompletableFuture<?> f = CompletableFuture.supplyAsync(() -> false);
f.cancel(true); // Stack trace makes it look as though CompletionException is thrown here
try {
f.join(); // Actually, CompletionException is thrown here.
} catch (CancellationException e) {
System.out.println("Exception was thrown from f.join()");
e.printStackTrace(System.out);
}
}
}
```
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
An exception with stack trace including the line number of the `f.join()` call, with a cause including the line number of the `f.cancel(true);` call.
```
Exception was thrown from f.join()
java.util.concurrent.CancellationException
at Main.main(Main.java:12)
Caused by
java.util.concurrent.CancellationException
at Main.main(Main.java:10)
```
ACTUAL -
An exception with stack trace including the line number of the `f.cancel(true);` call, and no indication of the line number of the `f.join()` call.
```
Exception was thrown from f.join()
java.util.concurrent.CancellationException
at java.base/java.util.concurrent.CompletableFuture.cancel(CompletableFuture.java:2396)
at Main.main(Main.java:10)
```
---------- BEGIN SOURCE ----------
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
// The main method must be in a class named "Main".
class Main {
public static void main(String[] args) {
System.out.println(System.getProperty("java.version"));
CompletableFuture<?> f = CompletableFuture.supplyAsync(() -> false);
f.cancel(true); // Stack trace makes it look as though CompletionException is thrown here
try {
f.join(); // Actually, CompletionException is thrown here.
} catch (CancellationException e) {
System.out.println("Exception was thrown from f.join()");
e.printStackTrace(System.out);
}
}
}
---------- END SOURCE ----------
https://stackoverflow.com/q/69034337/3788176
https://www.mycompiler.io/new/java?fork=AY0soH4
Here, a CompleteableFuture is cancelled, and then joined in quick succession. The join results in a CancellationException being thrown, which is expected.
However, the stack trace of the exception thrown is the stack trace captured at the time of the `f.cancel(true);` call, which leads to the erroneous impression that the exception is being _thrown_ on the `f.cancel(true);` call.
In a more realistic production scenario, the `cancel` and `join` calls are probably not going to be as close together as that. This could lead to a total wild goose chase of trying to work out why an exception was being thrown in one place (and potentially make it look, confusingly, as though statements after that exception were still being invoked), whereas in fact execution is being stopped somewhere completely different.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run source code
```
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
// The main method must be in a class named "Main".
class Main {
public static void main(String[] args) {
System.out.println(System.getProperty("java.version"));
CompletableFuture<?> f = CompletableFuture.supplyAsync(() -> false);
f.cancel(true); // Stack trace makes it look as though CompletionException is thrown here
try {
f.join(); // Actually, CompletionException is thrown here.
} catch (CancellationException e) {
System.out.println("Exception was thrown from f.join()");
e.printStackTrace(System.out);
}
}
}
```
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
An exception with stack trace including the line number of the `f.join()` call, with a cause including the line number of the `f.cancel(true);` call.
```
Exception was thrown from f.join()
java.util.concurrent.CancellationException
at Main.main(Main.java:12)
Caused by
java.util.concurrent.CancellationException
at Main.main(Main.java:10)
```
ACTUAL -
An exception with stack trace including the line number of the `f.cancel(true);` call, and no indication of the line number of the `f.join()` call.
```
Exception was thrown from f.join()
java.util.concurrent.CancellationException
at java.base/java.util.concurrent.CompletableFuture.cancel(CompletableFuture.java:2396)
at Main.main(Main.java:10)
```
---------- BEGIN SOURCE ----------
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
// The main method must be in a class named "Main".
class Main {
public static void main(String[] args) {
System.out.println(System.getProperty("java.version"));
CompletableFuture<?> f = CompletableFuture.supplyAsync(() -> false);
f.cancel(true); // Stack trace makes it look as though CompletionException is thrown here
try {
f.join(); // Actually, CompletionException is thrown here.
} catch (CancellationException e) {
System.out.println("Exception was thrown from f.join()");
e.printStackTrace(System.out);
}
}
}
---------- END SOURCE ----------