Description
Describe the bug
I have a piece of production code which uses ListenableFuture.future()
to bridge the gap between blocking code and code using coroutines. In essence the code using coroutines does a few network requests and the blocking code uses ListenableFuture.future()
followed by Future.get()
. I have observed that Future.get()
throws java.util.concurrent.CancellationException
wrapping kotlinx.coroutines.JobCancellationException
wrapping network exception. There is no explicit cancellations for the network calls and latencies are well below framework timeouts.
As far as I understand, Kotlin coroutines machinery should have unwrapped the CancellationException
and Future.get()
should have completed with ExecutionException
wrapping the network errors. I checked ListenableFuture.future()
code and it seems to me that CancellationException
might not be unwrapped: JobListenableFuture
receives cancellation exception and sets it as Canceled result to auxFuture (see JobListenableFuture.completeExceptionallyOrCancel()), when result is accessed it is converted back to CancellationException
(see JobListenableFuture.getInternal())
Could it be the case that ListenableFuture.future()
does not always correctly unwrap CancellationException
?
Provide a Reproducer
Sorry, can't provide a reproducer but I am ready to answer additional questions.