You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This issue is tricky as CoroutineScope.future ktdoc mentions this behavior:
Note that the error and cancellation semantics of future are subtly different than asListenableFuture’s.
In particular, any exception that happens in the coroutine after returned future is successfully cancelled
will be passed to the CoroutineExceptionHandler from the context. See ListenableFutureCoroutine for details.
I'd like to argue here it is not a good one and actually it means interface of ListenableFuture is incorrectly implemented by CoroutineScope.future -- ListenableFuture contract has cancel() method and it doesn't mention it can sometimes crash whole app. Due to that it fails "Liskov substitution principle" -- one can not use this specific impl of ListenableFuture instead of other ListenableFuture implementations.
To substantiate my observation this trivial code already sporadically will crash due to future behavior:
@Test
funcancellation_withFailureReportingRace_crashesCoroutineScope(): Unit= runBlocking(Dispatchers.IO) {
val innerFuture =SettableFuture.create<Unit>()
val outerFuture = future { innerFuture.await() }
launch { innerFuture.setException(IOException()) }
launch { outerFuture.cancel(false) }
// NOTE: This will sporadically crash, I'd expect the failure to be only present// in 'outterFuture'/'innerFuture'. I think unhandled exception in CoroutineScope// should not happen here.
}
I'm aware of #2774. I decided to create new issue as it is not about cancel/cancel race, although making cancel atomic might fix both. I don't think making cancel atomic will be fully possible due to constructs such as NonCancellable, but it would fix some issues.
The text was updated successfully, but these errors were encountered:
…oroutineExceptionHandler.
See Kotlin#2774 and Kotlin#2791 for more context.
This change makes `future` coroutine builder consistent with `java.util.concurrent.FutureTask` which also drops exceptions that happens after successful cancellation.
…oroutineExceptionHandler (Kotlin#2840)
This change makes `future` coroutine builder consistent with `java.util.concurrent.FutureTask` which also drops exceptions that happen after successful cancellation.
FixesKotlin#2774FixesKotlin#2791
…oroutineExceptionHandler (Kotlin#2840)
This change makes `future` coroutine builder consistent with `java.util.concurrent.FutureTask` which also drops exceptions that happen after successful cancellation.
FixesKotlin#2774FixesKotlin#2791
This issue is tricky as
CoroutineScope.future
ktdoc mentions this behavior:I'd like to argue here it is not a good one and actually it means interface of
ListenableFuture
is incorrectly implemented byCoroutineScope.future
--ListenableFuture
contract hascancel()
method and it doesn't mention it can sometimes crash whole app. Due to that it fails "Liskov substitution principle" -- one can not use this specific impl ofListenableFuture
instead of otherListenableFuture
implementations.To substantiate my observation this trivial code already sporadically will crash due to
future
behavior:I'm aware of #2774. I decided to create new issue as it is not about cancel/cancel race, although making cancel atomic might fix both. I don't think making cancel atomic will be fully possible due to constructs such as
NonCancellable
, but it would fix some issues.The text was updated successfully, but these errors were encountered: