Skip to content

withContext doesn't check for cancellation before running the block #785

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
LouisCAD opened this issue Nov 1, 2018 · 3 comments
Closed

Comments

@LouisCAD
Copy link
Contributor

LouisCAD commented Nov 1, 2018

The current implementation of withContext doesn't seem to check for cancellation (like yield() would for example) before running the passed block.
I didn't double check, but if I remember correctly, it doesn't check for cancellation after running the block either.

I think withContext checked for cancellation before and after running the block in the past (at some point before 1.0). I don't recall seeing any release notes about this though, so maybe I made false assumptions.

Anyway, I think it would be great to throw a CancellationException if the coroutine has been cancelled before running the block, and after it has been run before resuming the parent coroutine.

Cancellation is an important part of the efficiency coroutines brings to our programs. The earlier you stop doing something no longer needed, the earlier you start saving resources.

@qwwdfsad
Copy link
Collaborator

qwwdfsad commented Nov 6, 2018

I've partially addressed this issue in #791
All builders now unconditionally check cancellation status on exit.

I don't think it's really necessary to check it on the beginning of the block because it will be thrown on the first suspension point anyway, and if you are using some in-place builder you will suspend soon. While a desire to insert cancellation checks everywhere is understandable, we should remember that they are not free.

@LouisCAD
Copy link
Contributor Author

LouisCAD commented Nov 6, 2018

Nothing is free, but I'm wondering about the cost of checking the boolean property isActive and proceed on cancellation only when it's false. Is accessing this property costly?

About checking cancellation only on exit, I'm now wondering if checking cancellation before enter is useful in practical use cases, as you usually launch the coroutine already on the first dispatcher you want to use, and if you switch afterwards, it was likely because of previous suspension points (that may check for cancellation before you reach withContext). Do you think there are practical use cases for this? If there is none, #791 probably resolves this issue on its own.

@Tolriq
Copy link

Tolriq commented Nov 6, 2018

Can I ask a small confirmation as my tests did gave a different result about withContext checking for cancellation at the end.

@qwwdfsad does your PR changes also withContext and it is currently not checking?

I've made a lot of tests and finally left the code secure with a manual check for isActive after withContext

        launch {
            val result = withContext(IO) { repository.getAll() }
            if (isActive) {
                liveData.value = result
            }
        }

But from all my tests when cancelling the coroutine it's stopped before reaching the if.

elizarov added a commit that referenced this issue Feb 22, 2019
* Immediately check is the new context is cancelled and throw
  CancellationException as needed
* Properly explain cancellation behavior in documentation

Fixes #962
Fixes #785
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