Skip to content

Can ListenableFuture.future() not unwrap CancellationException when needed? #4347

Open
@ParafeniukMikalaj

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.

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions