Skip to content

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

Open
@ParafeniukMikalaj

Description

@ParafeniukMikalaj

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

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