question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Provide a way to cancel a running coroutine immediately

See original GitHub issue

When using blocking IO or computations the coroutine won’t be cancelled until the operation is complete meaning finally and invokeOnCompletion blocks can be called long after the parent job is cancelled.

Here’s an example:

class MyPresenter {
  fun loadStuff() {
    scope.launch {
      view.showProgress()
      try {
        performNetworkRequest()
      } catch(e: Exception) {
        view.hideProgress()
      }
    }
  }
}

The example above might crash if the performNetworkRequest isn’t cancelled before the view is detached from the presenter.

Currently the only way around this is to either use suspendCancellableCoroutine and perform a context switch to suspend the coroutine or to use invokeOnCompletion(onCancelling = true) (which is marked internal).

Perhaps a special context could be added to indicate that the result of an operation should be ignored when cancelling.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:6 (6 by maintainers)

github_iconTop GitHub Comments

2reactions
zach-klippensteincommented, Aug 20, 2019

On the JVM, there’s no generic way to force cancellation for any blocking operation. Some APIs have the ability to cancel, others you can work around with thread interruptions. But it’s up to the integration with your particular blocking API to handle actually cancelling the blocking operation. If you’re using Retrofit’s coroutine integration, network requests will automatically be cancelled when the coroutine is cancelled.

Even if you can’t actually cancel the operation, as long as the network request suspends the current coroutine (which it will if it changes context), the cancellation exception should be getting thrown from that function when it finishes at least. Catch and rethrow CancellationException, or check if e is CancellationException, before updating view state again. In general, swallowing CancellationExceptions (or generic Exceptions) is usually not a great idea unless you’re really sure that’s what you want to do.

0reactions
ansmancommented, Aug 20, 2019

I created this function now that would fix this. Thanks for the suggestion.

suspend inline fun <R> withCancellableContext(
    context: CoroutineContext,
    crossinline block: CoroutineScope.() -> R
): R {
    val job = GlobalScope.async(context) {
        runCatching(block)
    }
    val result = try {
        job.await()
    } catch (e: CancellationException) {
        job.cancel()
        throw e
    }
    return result.getOrThrow()
}
Read more comments on GitHub >

github_iconTop Results From Across the Web

How To Stop Or Cancel A Kotlin Coroutine ... - Stack Overflow
A kotlin coroutine must cooperate to allow cancellation. That means it has some check points calling one suspend function.
Read more >
Cancellation in coroutines - Medium
If we just call cancel , it doesn't mean that the coroutine work will just stop. If you're performing some relatively heavy computation,...
Read more >
Cancellation and timeouts | Kotlin
This section covers coroutine cancellation and timeouts. Cancelling coroutine execution. In a long-running application you might need fine- ...
Read more >
Cancellation in Kotlin Coroutines - Kt. Academy
The first one is to use the yield() function from time to time. This function suspends and immediately resumes a coroutine. This gives...
Read more >
Cancelling coroutines - Lanky Dan Blog
We have looked at how to cancel a job and how to write a coroutine that can be cancelled. A job can be...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found