Skip to content

kotlinx.coroutines.guava ListenableFuture cancellation #1346

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
yorickhenning opened this issue Jul 16, 2019 · 1 comment
Closed

kotlinx.coroutines.guava ListenableFuture cancellation #1346

yorickhenning opened this issue Jul 16, 2019 · 1 comment

Comments

@yorickhenning
Copy link
Contributor

I've found a few issues in ListenableFuture.kt with respect to Future's interface contract and with cancellation propagation:

  • Propagation of cancellation through asListenableFuture() is unidirectional; cancellation should be bidirectionally cooperative for any chain of Deferred and/or LF<> through transformation
  • Cancellation of a Future from asListenableFuture() through future.setFuture(someCancelledFuture) is broken; this should cancel future and doesn't
  • Future's happens-after contract with isCancelled() is (I think) broken in some cases, but this is hard to nail down; a Future can never return true from any more than one call to Future.cancel(), but I think the current asListenableFuture() Future can
  • Cancelling asListenableFuture() without interruption doesn't propagate to the deferred without interruption, which seems wrong? It's possible to cleanly cancel in this case.
  • Cancelling a Deferred with a CancellationException cause won't propagate the cause to an asListenableFuture() created from the Deferred - the cause and message are lost
  • Most of these subtler semantics aren't documented; there are some strange intersections between of what Job cancellation means and what Future cancellation means

These corner cases matter when using .guava as a migration layer in codebases where other implementations of Future or ListenableFuture/AbstractFuture are present. This is especially true for production code relying on cancel() behaviour to perform atomic work, or to efficiently clean up servlets or other somewhat-long-running tasks.

I've nailed down the problematic properties with unit tests. I've got a PR fixing them and documenting .guava pending.

There's an existing discussion on some related semantics around await() that don't address asListenableFuture() but do intersect a bit.

From the Guava perspective, the PR's semantics are "more correct" for ListenableFuture semantics, and should be a no-op or an improvement for Deferred semantics. There are some optimizations around atomic reads, too.

@qwwdfsad
Copy link
Member

Fixed in 1.3.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants